diff options
60 files changed, 6802 insertions, 709 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md index c4518bf..f0d67a5 100755 --- a/doc/docs/doc/README.md +++ b/doc/docs/doc/README.md | |||
@@ -16,19 +16,29 @@ Yue (ζ) is the name of moon in Chinese and it's pronounced as [jyΙ]. | |||
16 | ### An Overview of YueScript | 16 | ### An Overview of YueScript |
17 | ```moonscript | 17 | ```moonscript |
18 | -- import syntax | 18 | -- import syntax |
19 | import "yue" as :p, :to_lua | 19 | import p, to_lua from "yue" |
20 | 20 | ||
21 | -- object literals | 21 | -- object literals |
22 | inventory = | 22 | inventory = |
23 | equipment: | 23 | equipment: |
24 | * "sword" | 24 | - "sword" |
25 | * "shield" | 25 | - "shield" |
26 | items: | 26 | items: |
27 | * name: "potion" | 27 | - name: "potion" |
28 | count: 10 | 28 | count: 10 |
29 | * name: "bread" | 29 | - name: "bread" |
30 | count: 3 | 30 | count: 3 |
31 | 31 | ||
32 | -- list comprehension | ||
33 | map = (arr, action) -> | ||
34 | [action item for item in *arr] | ||
35 | |||
36 | filter = (arr, cond) -> | ||
37 | [item for item in *arr when cond item] | ||
38 | |||
39 | reduce = (arr, init, action): init -> | ||
40 | init = action init, item for item in *arr | ||
41 | |||
32 | -- pipe operator | 42 | -- pipe operator |
33 | [1, 2, 3] | 43 | [1, 2, 3] |
34 | |> map (x) -> x * 2 | 44 | |> map (x) -> x * 2 |
@@ -51,19 +61,29 @@ export π = "ζδΉθζ¬" | |||
51 | <YueDisplay> | 61 | <YueDisplay> |
52 | <pre> | 62 | <pre> |
53 | -- import syntax | 63 | -- import syntax |
54 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
55 | 65 | ||
56 | -- object literals | 66 | -- object literals |
57 | inventory = | 67 | inventory = |
58 | equipment: | 68 | equipment: |
59 | * "sword" | 69 | - "sword" |
60 | * "shield" | 70 | - "shield" |
61 | items: | 71 | items: |
62 | * name: "potion" | 72 | - name: "potion" |
63 | count: 10 | 73 | count: 10 |
64 | * name: "bread" | 74 | - name: "bread" |
65 | count: 3 | 75 | count: 3 |
66 | 76 | ||
77 | -- list comprehension | ||
78 | map = (arr, action) -> | ||
79 | [action item for item in *arr] | ||
80 | |||
81 | filter = (arr, cond) -> | ||
82 | [item for item in *arr when cond item] | ||
83 | |||
84 | reduce = (arr, init, action): init -> | ||
85 | init = action init, item for item in *arr | ||
86 | |||
67 | -- pipe operator | 87 | -- pipe operator |
68 | [1, 2, 3] | 88 | [1, 2, 3] |
69 | |> map (x) -> x * 2 | 89 | |> map (x) -> x * 2 |
@@ -132,14 +152,14 @@ export π = "ζδΉθζ¬" | |||
132 | 152 | ||
133 |  Use YueScript module in Lua: | 153 |  Use YueScript module in Lua: |
134 | 154 | ||
135 | * **Case 1** | 155 | * **Case 1** |
136 | Require "your_yuescript_entry.yue" in Lua. | 156 | Require "your_yuescript_entry.yue" in Lua. |
137 | ```Lua | 157 | ```Lua |
138 | require("yue")("your_yuescript_entry") | 158 | require("yue")("your_yuescript_entry") |
139 | ``` | 159 | ``` |
140 |  And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. | 160 |  And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. |
141 | 161 | ||
142 | * **Case 2** | 162 | * **Case 2** |
143 | Require YueScript module and rewite message by hand. | 163 | Require YueScript module and rewite message by hand. |
144 | ```lua | 164 | ```lua |
145 | local yue = require("yue") | 165 | local yue = require("yue") |
@@ -151,7 +171,7 @@ end, function(err) | |||
151 | end) | 171 | end) |
152 | ``` | 172 | ``` |
153 | 173 | ||
154 | * **Case 3** | 174 | * **Case 3** |
155 | Use the YueScript compiler function in Lua. | 175 | Use the YueScript compiler function in Lua. |
156 | ```lua | 176 | ```lua |
157 | local yue = require("yue") | 177 | local yue = require("yue") |
@@ -203,12 +223,12 @@ Usage: yue [options|files|directories] ... | |||
203 | Execute without options to enter REPL, type symbol '$' | 223 | Execute without options to enter REPL, type symbol '$' |
204 | in a single line to start/stop multi-line mode | 224 | in a single line to start/stop multi-line mode |
205 | ``` | 225 | ``` |
206 |   Use cases: | 226 |   Use cases: |
207 |   Recursively compile every YueScript file with extension **.yue** under current path: **yue .** | 227 |   Recursively compile every YueScript file with extension **.yue** under current path: **yue .** |
208 |   Compile and save results to a target path: **yue -t /target/path/ .** | 228 |   Compile and save results to a target path: **yue -t /target/path/ .** |
209 |   Compile and reserve debug info: **yue -l .** | 229 |   Compile and reserve debug info: **yue -l .** |
210 |   Compile and generate minified codes: **yue -m .** | 230 |   Compile and generate minified codes: **yue -m .** |
211 |   Execute raw codes: **yue -e 'print 123'** | 231 |   Execute raw codes: **yue -e 'print 123'** |
212 |   Execute a YueScript file: **yue -e main.yue** | 232 |   Execute a YueScript file: **yue -e main.yue** |
213 | 233 | ||
214 | ## Macro | 234 | ## Macro |
@@ -424,6 +444,54 @@ print "Valid enum type:", $BodyType Static | |||
424 | </pre> | 444 | </pre> |
425 | </YueDisplay> | 445 | </YueDisplay> |
426 | 446 | ||
447 | ### Argument Validation | ||
448 | |||
449 | You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time. | ||
450 | |||
451 | ```moonscript | ||
452 | macro printNumAndStr = (num `Num, str `String) -> | | ||
453 | print( | ||
454 | #{num} | ||
455 | #{str} | ||
456 | ) | ||
457 | |||
458 | $printNumAndStr 123, "hello" | ||
459 | ``` | ||
460 | <YueDisplay> | ||
461 | <pre> | ||
462 | macro printNumAndStr = (num `Num, str `String) -> | | ||
463 | print( | ||
464 | #{num} | ||
465 | #{str} | ||
466 | ) | ||
467 | |||
468 | $printNumAndStr 123, "hello" | ||
469 | </pre> | ||
470 | </YueDisplay> | ||
471 | |||
472 | If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place. | ||
473 | |||
474 | ```moonscript | ||
475 | macro printNumAndStr = (num, str) -> | ||
476 | error "expected Num as first argument" unless $is_ast Num, num | ||
477 | error "expected String as second argument" unless $is_ast String, str | ||
478 | "print(#{num}, #{str})" | ||
479 | |||
480 | $printNumAndStr 123, "hello" | ||
481 | ``` | ||
482 | <YueDisplay> | ||
483 | <pre> | ||
484 | macro printNumAndStr = (num, str) -> | ||
485 | error "expected Num as first argument" unless $is_ast Num, num | ||
486 | error "expected String as second argument" unless $is_ast String, str | ||
487 | "print(#{num}, #{str})" | ||
488 | |||
489 | $printNumAndStr 123, "hello" | ||
490 | </pre> | ||
491 | </YueDisplay> | ||
492 | |||
493 | For more details about available AST nodes, please refer to the uppercased definitions in [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp). | ||
494 | |||
427 | ## Operator | 495 | ## Operator |
428 | 496 | ||
429 | All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. | 497 | All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. |
@@ -566,11 +634,26 @@ merge = {...a, ...b} | |||
566 | </pre> | 634 | </pre> |
567 | </YueDisplay> | 635 | </YueDisplay> |
568 | 636 | ||
637 | ### Table Reversed Indexing | ||
638 | |||
639 | You can use the **#** operator to get the last elements of a table. | ||
640 | |||
641 | ```moonscript | ||
642 | last = data.items[#] | ||
643 | second_last = data.items[#-1] | ||
644 | ``` | ||
645 | <YueDisplay> | ||
646 | <pre> | ||
647 | last = data.items[#] | ||
648 | second_last = data.items[#-1] | ||
649 | </pre> | ||
650 | </YueDisplay> | ||
651 | |||
569 | ### Metatable | 652 | ### Metatable |
570 | 653 | ||
571 | The **<>** operator can be used as a shortcut for metatable manipulation. | 654 | The **<>** operator can be used as a shortcut for metatable manipulation. |
572 | 655 | ||
573 | * **Metatable Creation** | 656 | * **Metatable Creation** |
574 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. | 657 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. |
575 | 658 | ||
576 | ```moonscript | 659 | ```moonscript |
@@ -606,7 +689,7 @@ close _ = <close>: -> print "out of scope" | |||
606 | </pre> | 689 | </pre> |
607 | </YueDisplay> | 690 | </YueDisplay> |
608 | 691 | ||
609 | * **Metatable Accessing** | 692 | * **Metatable Accessing** |
610 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. | 693 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. |
611 | 694 | ||
612 | ```moonscript | 695 | ```moonscript |
@@ -630,7 +713,7 @@ print tb.item | |||
630 | </pre> | 713 | </pre> |
631 | </YueDisplay> | 714 | </YueDisplay> |
632 | 715 | ||
633 | * **Metatable Destructure** | 716 | * **Metatable Destructure** |
634 | Destruct metatable with metamethod key surrounded by **<>**. | 717 | Destruct metatable with metamethod key surrounded by **<>**. |
635 | 718 | ||
636 | ```moonscript | 719 | ```moonscript |
@@ -732,34 +815,45 @@ a ??= false | |||
732 | 815 | ||
733 | ### Implicit Object | 816 | ### Implicit Object |
734 | 817 | ||
735 | You can write a list of implicit structures that starts with the symbol **\*** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. | 818 | You can write a list of implicit structures that starts with the symbol **\*** or **-** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. |
819 | |||
736 | ```moonscript | 820 | ```moonscript |
821 | -- assignment with implicit object | ||
737 | list = | 822 | list = |
738 | * 1 | 823 | * 1 |
739 | * 2 | 824 | * 2 |
740 | * 3 | 825 | * 3 |
741 | 826 | ||
827 | -- function call with implicit object | ||
742 | func | 828 | func |
743 | * 1 | 829 | * 1 |
744 | * 2 | 830 | * 2 |
745 | * 3 | 831 | * 3 |
746 | 832 | ||
833 | -- return with implicit object | ||
834 | f = -> | ||
835 | return | ||
836 | * 1 | ||
837 | * 2 | ||
838 | * 3 | ||
839 | |||
840 | -- table with implicit object | ||
747 | tb = | 841 | tb = |
748 | name: "abc" | 842 | name: "abc" |
749 | 843 | ||
750 | values: | 844 | values: |
751 | * "a" | 845 | - "a" |
752 | * "b" | 846 | - "b" |
753 | * "c" | 847 | - "c" |
754 | 848 | ||
755 | objects: | 849 | objects: |
756 | * name: "a" | 850 | - name: "a" |
757 | value: 1 | 851 | value: 1 |
758 | func: => @value + 1 | 852 | func: => @value + 1 |
759 | tb: | 853 | tb: |
760 | fieldA: 1 | 854 | fieldA: 1 |
761 | 855 | ||
762 | * name: "b" | 856 | - name: "b" |
763 | value: 2 | 857 | value: 2 |
764 | func: => @value + 2 | 858 | func: => @value + 2 |
765 | tb: { } | 859 | tb: { } |
@@ -767,32 +861,42 @@ tb = | |||
767 | ``` | 861 | ``` |
768 | <YueDisplay> | 862 | <YueDisplay> |
769 | <pre> | 863 | <pre> |
864 | -- assignment with implicit object | ||
770 | list = | 865 | list = |
771 | * 1 | 866 | * 1 |
772 | * 2 | 867 | * 2 |
773 | * 3 | 868 | * 3 |
774 | 869 | ||
870 | -- function call with implicit object | ||
775 | func | 871 | func |
776 | * 1 | 872 | * 1 |
777 | * 2 | 873 | * 2 |
778 | * 3 | 874 | * 3 |
779 | 875 | ||
876 | -- return with implicit object | ||
877 | f = -> | ||
878 | return | ||
879 | * 1 | ||
880 | * 2 | ||
881 | * 3 | ||
882 | |||
883 | -- table with implicit object | ||
780 | tb = | 884 | tb = |
781 | name: "abc" | 885 | name: "abc" |
782 | 886 | ||
783 | values: | 887 | values: |
784 | * "a" | 888 | - "a" |
785 | * "b" | 889 | - "b" |
786 | * "c" | 890 | - "c" |
787 | 891 | ||
788 | objects: | 892 | objects: |
789 | * name: "a" | 893 | - name: "a" |
790 | value: 1 | 894 | value: 1 |
791 | func: => @value + 1 | 895 | func: => @value + 1 |
792 | tb: | 896 | tb: |
793 | fieldA: 1 | 897 | fieldA: 1 |
794 | 898 | ||
795 | * name: "b" | 899 | - name: "b" |
796 | value: 2 | 900 | value: 2 |
797 | func: => @value + 2 | 901 | func: => @value + 2 |
798 | tb: { } | 902 | tb: { } |
@@ -860,7 +964,7 @@ do | |||
860 | 964 | ||
861 | The export statement offers a concise way to define modules. | 965 | The export statement offers a concise way to define modules. |
862 | 966 | ||
863 | * **Named Export** | 967 | * **Named Export** |
864 | Named export will define a local variable as well as adding a field in the exported table. | 968 | Named export will define a local variable as well as adding a field in the exported table. |
865 | 969 | ||
866 | ```moonscript | 970 | ```moonscript |
@@ -924,7 +1028,7 @@ export["a-b-c"] = 123 | |||
924 | </pre> | 1028 | </pre> |
925 | </YueDisplay> | 1029 | </YueDisplay> |
926 | 1030 | ||
927 | * **Unnamed Export** | 1031 | * **Unnamed Export** |
928 | Unnamed export will add the target item into the array part of the exported table. | 1032 | Unnamed export will add the target item into the array part of the exported table. |
929 | 1033 | ||
930 | ```moonscript | 1034 | ```moonscript |
@@ -954,7 +1058,7 @@ export with tmp | |||
954 | </pre> | 1058 | </pre> |
955 | </YueDisplay> | 1059 | </YueDisplay> |
956 | 1060 | ||
957 | * **Default Export** | 1061 | * **Default Export** |
958 | Using the **default** keyword in export statement to replace the exported table with any thing. | 1062 | Using the **default** keyword in export statement to replace the exported table with any thing. |
959 | 1063 | ||
960 | ```moonscript | 1064 | ```moonscript |
@@ -1202,7 +1306,7 @@ If the destructuring statement is complicated, feel free to spread it out over a | |||
1202 | </pre> | 1306 | </pre> |
1203 | </YueDisplay> | 1307 | </YueDisplay> |
1204 | 1308 | ||
1205 | Itβs common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: | 1309 | It's common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: |
1206 | 1310 | ||
1207 | ```moonscript | 1311 | ```moonscript |
1208 | {:concat, :insert} = table | 1312 | {:concat, :insert} = table |
@@ -1246,6 +1350,52 @@ You can use `_` as placeholder when doing a list destructuring: | |||
1246 | </pre> | 1350 | </pre> |
1247 | </YueDisplay> | 1351 | </YueDisplay> |
1248 | 1352 | ||
1353 | ### Range Destructuring | ||
1354 | |||
1355 | You can use the spread operator `...` in list destructuring to capture a range of values. This is useful when you want to extract specific elements from the beginning and end of a list while collecting the rest in between. | ||
1356 | |||
1357 | ```moonscript | ||
1358 | orders = ["first", "second", "third", "fourth", "last"] | ||
1359 | [first, ...bulk, last] = orders | ||
1360 | print first -- prints: first | ||
1361 | print bulk -- prints: {"second", "third", "fourth"} | ||
1362 | print last -- prints: last | ||
1363 | ``` | ||
1364 | <YueDisplay> | ||
1365 | <pre> | ||
1366 | orders = ["first", "second", "third", "fourth", "last"] | ||
1367 | [first, ...bulk, last] = orders | ||
1368 | print first -- prints: first | ||
1369 | print bulk -- prints: {"second", "third", "fourth"} | ||
1370 | print last -- prints: last | ||
1371 | </pre> | ||
1372 | </YueDisplay> | ||
1373 | |||
1374 | The spread operator can be used in different positions to capture different ranges, and you can use `_` as a placeholder for the values you don't want to capture: | ||
1375 | |||
1376 | ```moonscript | ||
1377 | -- Capture everything after first element | ||
1378 | [first, ...rest] = orders | ||
1379 | |||
1380 | -- Capture everything before last element | ||
1381 | [...start, last] = orders | ||
1382 | |||
1383 | -- Capture things except the middle elements | ||
1384 | [first, ..._, last] = orders | ||
1385 | ``` | ||
1386 | <YueDisplay> | ||
1387 | <pre> | ||
1388 | -- Capture everything after first element | ||
1389 | [first, ...rest] = orders | ||
1390 | |||
1391 | -- Capture everything before last element | ||
1392 | [...start, last] = orders | ||
1393 | |||
1394 | -- Capture things except the middle elements | ||
1395 | [first, ..._, last] = orders | ||
1396 | </pre> | ||
1397 | </YueDisplay> | ||
1398 | |||
1249 | ### Destructuring In Other Places | 1399 | ### Destructuring In Other Places |
1250 | 1400 | ||
1251 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: | 1401 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: |
@@ -1475,6 +1625,47 @@ catch err | |||
1475 | </pre> | 1625 | </pre> |
1476 | </YueDisplay> | 1626 | </YueDisplay> |
1477 | 1627 | ||
1628 | ### Try? | ||
1629 | |||
1630 | `try?` is a simplified use for error handling syntax that omit the boolean status from the `try` statement, and it will return the result from the try block when success, return nil instead of error object otherwise. | ||
1631 | |||
1632 | ```moonscript | ||
1633 | a, b, c = try? func! | ||
1634 | |||
1635 | -- with nil coalescing operator | ||
1636 | a = (try? func!) ?? "default" | ||
1637 | |||
1638 | -- as function argument | ||
1639 | f try? func! | ||
1640 | |||
1641 | -- with catch block | ||
1642 | f try? | ||
1643 | print 123 | ||
1644 | func! | ||
1645 | catch e | ||
1646 | print e | ||
1647 | e | ||
1648 | ``` | ||
1649 | <YueDisplay> | ||
1650 | <pre> | ||
1651 | a, b, c = try? func! | ||
1652 | |||
1653 | -- with nil coalescing operator | ||
1654 | a = (try? func!) ?? "default" | ||
1655 | |||
1656 | -- as function argument | ||
1657 | f try? func! | ||
1658 | |||
1659 | -- with catch block | ||
1660 | f try? | ||
1661 | print 123 | ||
1662 | func! | ||
1663 | catch e | ||
1664 | print e | ||
1665 | e | ||
1666 | </pre> | ||
1667 | </YueDisplay> | ||
1668 | |||
1478 | ## Attributes | 1669 | ## Attributes |
1479 | 1670 | ||
1480 | Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. | 1671 | Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. |
@@ -1503,6 +1694,19 @@ const {:a, :b, c, d} = tb | |||
1503 | </pre> | 1694 | </pre> |
1504 | </YueDisplay> | 1695 | </YueDisplay> |
1505 | 1696 | ||
1697 | You can also declare a global variable to be `const`. | ||
1698 | |||
1699 | ```moonscript | ||
1700 | global const Constant = 123 | ||
1701 | -- Constant = 1 | ||
1702 | ``` | ||
1703 | <YueDisplay> | ||
1704 | <pre> | ||
1705 | global const Constant = 123 | ||
1706 | -- Constant = 1 | ||
1707 | </pre> | ||
1708 | </YueDisplay> | ||
1709 | |||
1506 | ## Literals | 1710 | ## Literals |
1507 | 1711 | ||
1508 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. | 1712 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. |
@@ -1535,12 +1739,73 @@ You can use underscores in a number literal to increase readability. | |||
1535 | ```moonscript | 1739 | ```moonscript |
1536 | integer = 1_000_000 | 1740 | integer = 1_000_000 |
1537 | hex = 0xEF_BB_BF | 1741 | hex = 0xEF_BB_BF |
1742 | binary = 0B10011 | ||
1538 | ``` | 1743 | ``` |
1539 | <YueDisplay> | 1744 | <YueDisplay> |
1540 | 1745 | ||
1541 | <pre> | 1746 | <pre> |
1542 | integer = 1_000_000 | 1747 | integer = 1_000_000 |
1543 | hex = 0xEF_BB_BF | 1748 | hex = 0xEF_BB_BF |
1749 | binary = 0B10011 | ||
1750 | </pre> | ||
1751 | </YueDisplay> | ||
1752 | |||
1753 | ### YAML Multiline String | ||
1754 | |||
1755 | The `|` prefix introduces a YAML-style multiline string literal: | ||
1756 | |||
1757 | ```moonscript | ||
1758 | str = | | ||
1759 | key: value | ||
1760 | list: | ||
1761 | - item1 | ||
1762 | - #{expr} | ||
1763 | ``` | ||
1764 | <YueDisplay> | ||
1765 | <pre> | ||
1766 | str = | | ||
1767 | key: value | ||
1768 | list: | ||
1769 | - item1 | ||
1770 | - #{expr} | ||
1771 | </pre> | ||
1772 | </YueDisplay> | ||
1773 | |||
1774 | This allows writing structured multiline text conveniently. All line breaks and indentation are preserved relative to the first non-empty line, and expressions inside `#{...}` are interpolated automatically as `tostring(expr)`. | ||
1775 | |||
1776 | YAML Multiline String automatically detects the common leading whitespace prefix (minimum indentation across all non-empty lines) and removes it from all lines. This makes it easy to indent your code visually without affecting the resulting string content. | ||
1777 | |||
1778 | ```moonscript | ||
1779 | fn = -> | ||
1780 | str = | | ||
1781 | foo: | ||
1782 | bar: baz | ||
1783 | return str | ||
1784 | ``` | ||
1785 | <YueDisplay> | ||
1786 | <pre> | ||
1787 | fn = -> | ||
1788 | str = | | ||
1789 | foo: | ||
1790 | bar: baz | ||
1791 | return str | ||
1792 | </pre> | ||
1793 | </YueDisplay> | ||
1794 | |||
1795 | Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures. | ||
1796 | |||
1797 | All special characters like quotes (`"`) and backslashes (`\`) in the YAMLMultiline block are automatically escaped so that the generated Lua string is syntactically valid and behaves as expected. | ||
1798 | |||
1799 | ```moonscript | ||
1800 | str = | | ||
1801 | path: "C:\Program Files\App" | ||
1802 | note: 'He said: "#{Hello}!"' | ||
1803 | ``` | ||
1804 | <YueDisplay> | ||
1805 | <pre> | ||
1806 | str = | | ||
1807 | path: "C:\Program Files\App" | ||
1808 | note: 'He said: "#{Hello}!"' | ||
1544 | </pre> | 1809 | </pre> |
1545 | </YueDisplay> | 1810 | </YueDisplay> |
1546 | 1811 | ||
@@ -1902,22 +2167,22 @@ x * 2 | |||
1902 | </pre> | 2167 | </pre> |
1903 | </YueDisplay> | 2168 | </YueDisplay> |
1904 | 2169 | ||
1905 | If you wish to have further code after your backcalls, you can set them aside with a do statement. | 2170 | If you wish to have further code after your backcalls, you can set them aside with a do statement. And the parentheses can be omitted with non-fat arrow functions. |
1906 | 2171 | ||
1907 | ```moonscript | 2172 | ```moonscript |
1908 | result, msg = do | 2173 | result, msg = do |
1909 | (data) <- readAsync "filename.txt" | 2174 | data <- readAsync "filename.txt" |
1910 | print data | 2175 | print data |
1911 | (info) <- processAsync data | 2176 | info <- processAsync data |
1912 | check info | 2177 | check info |
1913 | print result, msg | 2178 | print result, msg |
1914 | ``` | 2179 | ``` |
1915 | <YueDisplay> | 2180 | <YueDisplay> |
1916 | <pre> | 2181 | <pre> |
1917 | result, msg = do | 2182 | result, msg = do |
1918 | (data) <- readAsync "filename.txt" | 2183 | data <- readAsync "filename.txt" |
1919 | print data | 2184 | print data |
1920 | (info) <- processAsync data | 2185 | info <- processAsync data |
1921 | check info | 2186 | check info |
1922 | print result, msg | 2187 | print result, msg |
1923 | </pre> | 2188 | </pre> |
@@ -2248,6 +2513,45 @@ slice = [item for item in *items[,,2]] | |||
2248 | </pre> | 2513 | </pre> |
2249 | </YueDisplay> | 2514 | </YueDisplay> |
2250 | 2515 | ||
2516 | Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table. | ||
2517 | |||
2518 | ```moonscript | ||
2519 | -- take the last 4 items | ||
2520 | slice = [item for item in *items[-4,-1]] | ||
2521 | ``` | ||
2522 | <YueDisplay> | ||
2523 | <pre> | ||
2524 | -- take the last 4 items | ||
2525 | slice = [item for item in *items[-4,-1]] | ||
2526 | </pre> | ||
2527 | </YueDisplay> | ||
2528 | |||
2529 | The step size can also be negative, which means that the items are taken in reverse order. | ||
2530 | |||
2531 | ```moonscript | ||
2532 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2533 | ``` | ||
2534 | <YueDisplay> | ||
2535 | <pre> | ||
2536 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2537 | </pre> | ||
2538 | </YueDisplay> | ||
2539 | |||
2540 | #### Slicing Expression | ||
2541 | |||
2542 | Slicing can also be used as an expression. This is useful for getting a sub-list of a table. | ||
2543 | |||
2544 | ```moonscript | ||
2545 | -- take the 2nd and 4th items as a new list | ||
2546 | sub_list = items[2, 4] | ||
2547 | ``` | ||
2548 | <YueDisplay> | ||
2549 | <pre> | ||
2550 | -- take the 2nd and 4th items as a new list | ||
2551 | sub_list = items[2, 4] | ||
2552 | </pre> | ||
2553 | </YueDisplay> | ||
2554 | |||
2251 | ## For Loop | 2555 | ## For Loop |
2252 | 2556 | ||
2253 | There are two for loop forms, just like in Lua. A numeric one and a generic one: | 2557 | There are two for loop forms, just like in Lua. A numeric one and a generic one: |
@@ -2324,6 +2628,23 @@ doubled_evens = for i = 1, 20 | |||
2324 | </pre> | 2628 | </pre> |
2325 | </YueDisplay> | 2629 | </YueDisplay> |
2326 | 2630 | ||
2631 | In addition, for loops support break with a return value, allowing the loop itself to be used as an expression that exits early with a meaningful result. | ||
2632 | |||
2633 | For example, to find the first number greater than 10: | ||
2634 | |||
2635 | ```moonscript | ||
2636 | first_large = for n in *numbers | ||
2637 | break n if n > 10 | ||
2638 | ``` | ||
2639 | <YueDisplay> | ||
2640 | <pre> | ||
2641 | first_large = for n in *numbers | ||
2642 | break n if n > 10 | ||
2643 | </pre> | ||
2644 | </YueDisplay> | ||
2645 | |||
2646 | This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions. | ||
2647 | |||
2327 | You can also filter values by combining the for loop expression with the continue statement. | 2648 | You can also filter values by combining the for loop expression with the continue statement. |
2328 | 2649 | ||
2329 | For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. | 2650 | For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. |
@@ -2345,7 +2666,7 @@ print func_b! -- prints table object | |||
2345 | </pre> | 2666 | </pre> |
2346 | </YueDisplay> | 2667 | </YueDisplay> |
2347 | 2668 | ||
2348 | This is done to avoid the needless creation of tables for functions that donβt need to return the results of the loop. | 2669 | This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop. |
2349 | 2670 | ||
2350 | ## Repeat Loop | 2671 | ## Repeat Loop |
2351 | 2672 | ||
@@ -2624,28 +2945,26 @@ reader\parse_line! until reader\eof! | |||
2624 | 2945 | ||
2625 | ## Switch | 2946 | ## Switch |
2626 | 2947 | ||
2627 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. | 2948 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. In switch statement, you can also use assignment expression to store temporary variable value. |
2628 | 2949 | ||
2629 | ```moonscript | 2950 | ```moonscript |
2630 | name = "Dan" | 2951 | switch name := "Dan" |
2631 | switch name | ||
2632 | when "Robert" | 2952 | when "Robert" |
2633 | print "You are Robert" | 2953 | print "You are Robert" |
2634 | when "Dan", "Daniel" | 2954 | when "Dan", "Daniel" |
2635 | print "Your name, it's Dan" | 2955 | print "Your name, it's Dan" |
2636 | else | 2956 | else |
2637 | print "I don't know about your name" | 2957 | print "I don't know about you with name #{name}" |
2638 | ``` | 2958 | ``` |
2639 | <YueDisplay> | 2959 | <YueDisplay> |
2640 | <pre> | 2960 | <pre> |
2641 | name = "Dan" | 2961 | switch name := "Dan" |
2642 | switch name | ||
2643 | when "Robert" | 2962 | when "Robert" |
2644 | print "You are Robert" | 2963 | print "You are Robert" |
2645 | when "Dan", "Daniel" | 2964 | when "Dan", "Daniel" |
2646 | print "Your name, it's Dan" | 2965 | print "Your name, it's Dan" |
2647 | else | 2966 | else |
2648 | print "I don't know about your name" | 2967 | print "I don't know about you with name #{name}" |
2649 | </pre> | 2968 | </pre> |
2650 | </YueDisplay> | 2969 | </YueDisplay> |
2651 | 2970 | ||
@@ -2676,7 +2995,7 @@ next_number = switch b | |||
2676 | </pre> | 2995 | </pre> |
2677 | </YueDisplay> | 2996 | </YueDisplay> |
2678 | 2997 | ||
2679 | We can use the then keyword to write a switchβs when block on a single line. No extra keyword is needed to write the else block on a single line. | 2998 | We can use the then keyword to write a switch's when block on a single line. No extra keyword is needed to write the else block on a single line. |
2680 | 2999 | ||
2681 | ```moonscript | 3000 | ```moonscript |
2682 | msg = switch math.random(1, 5) | 3001 | msg = switch math.random(1, 5) |
@@ -2722,7 +3041,7 @@ else | |||
2722 | </pre> | 3041 | </pre> |
2723 | </YueDisplay> | 3042 | </YueDisplay> |
2724 | 3043 | ||
2725 | It is worth noting the order of the case comparison expression. The caseβs expression is on the left hand side. This can be useful if the caseβs expression wants to overwrite how the comparison is done by defining an eq metamethod. | 3044 | It is worth noting the order of the case comparison expression. The case's expression is on the left hand side. This can be useful if the case's expression wants to overwrite how the comparison is done by defining an eq metamethod. |
2726 | 3045 | ||
2727 | ### Table Matching | 3046 | ### Table Matching |
2728 | 3047 | ||
@@ -2782,6 +3101,123 @@ switch item | |||
2782 | </pre> | 3101 | </pre> |
2783 | </YueDisplay> | 3102 | </YueDisplay> |
2784 | 3103 | ||
3104 | You can also match against array elements, table fields, and even nested structures with array or table literals. | ||
3105 | |||
3106 | Match against array elements. | ||
3107 | |||
3108 | ```moonscript | ||
3109 | switch tb | ||
3110 | when [1, 2, 3] | ||
3111 | print "1, 2, 3" | ||
3112 | when [1, b, 3] | ||
3113 | print "1, #{b}, 3" | ||
3114 | when [1, 2, b = 3] -- b has a default value | ||
3115 | print "1, 2, #{b}" | ||
3116 | ``` | ||
3117 | <YueDisplay> | ||
3118 | <pre> | ||
3119 | switch tb | ||
3120 | when [1, 2, 3] | ||
3121 | print "1, 2, 3" | ||
3122 | when [1, b, 3] | ||
3123 | print "1, #{b}, 3" | ||
3124 | when [1, 2, b = 3] -- b has a default value | ||
3125 | print "1, 2, #{b}" | ||
3126 | </pre> | ||
3127 | </YueDisplay> | ||
3128 | |||
3129 | Match against table fields with destructuring. | ||
3130 | |||
3131 | ```moonscript | ||
3132 | switch tb | ||
3133 | when success: true, :result | ||
3134 | print "success", result | ||
3135 | when success: false | ||
3136 | print "failed", result | ||
3137 | else | ||
3138 | print "invalid" | ||
3139 | ``` | ||
3140 | <YueDisplay> | ||
3141 | <pre> | ||
3142 | switch tb | ||
3143 | when success: true, :result | ||
3144 | print "success", result | ||
3145 | when success: false | ||
3146 | print "failed", result | ||
3147 | else | ||
3148 | print "invalid" | ||
3149 | </pre> | ||
3150 | </YueDisplay> | ||
3151 | |||
3152 | Match against nested table structures. | ||
3153 | |||
3154 | ```moonscript | ||
3155 | switch tb | ||
3156 | when data: {type: "success", :content} | ||
3157 | print "success", content | ||
3158 | when data: {type: "error", :content} | ||
3159 | print "failed", content | ||
3160 | else | ||
3161 | print "invalid" | ||
3162 | ``` | ||
3163 | <YueDisplay> | ||
3164 | <pre> | ||
3165 | switch tb | ||
3166 | when data: {type: "success", :content} | ||
3167 | print "success", content | ||
3168 | when data: {type: "error", :content} | ||
3169 | print "failed", content | ||
3170 | else | ||
3171 | print "invalid" | ||
3172 | </pre> | ||
3173 | </YueDisplay> | ||
3174 | |||
3175 | Match against array of tables. | ||
3176 | |||
3177 | ```moonscript | ||
3178 | switch tb | ||
3179 | when [ | ||
3180 | {a: 1, b: 2} | ||
3181 | {a: 3, b: 4} | ||
3182 | {a: 5, b: 6} | ||
3183 | fourth | ||
3184 | ] | ||
3185 | print "matched", fourth | ||
3186 | ``` | ||
3187 | <YueDisplay> | ||
3188 | <pre> | ||
3189 | switch tb | ||
3190 | when [ | ||
3191 | {a: 1, b: 2} | ||
3192 | {a: 3, b: 4} | ||
3193 | {a: 5, b: 6} | ||
3194 | fourth | ||
3195 | ] | ||
3196 | print "matched", fourth | ||
3197 | </pre> | ||
3198 | </YueDisplay> | ||
3199 | |||
3200 | Match against a list and capture a range of elements. | ||
3201 | |||
3202 | ```moonscript | ||
3203 | segments = ["admin", "users", "logs", "view"] | ||
3204 | switch segments | ||
3205 | when [...groups, resource, action] | ||
3206 | print "Group:", groups -- prints: {"admin", "users"} | ||
3207 | print "Resource:", resource -- prints: "logs" | ||
3208 | print "Action:", action -- prints: "view" | ||
3209 | ``` | ||
3210 | <YueDisplay> | ||
3211 | <pre> | ||
3212 | segments = ["admin", "users", "logs", "view"] | ||
3213 | switch segments | ||
3214 | when [...groups, resource, action] | ||
3215 | print "Group:", groups -- prints: {"admin", "users"} | ||
3216 | print "Resource:", resource -- prints: "logs" | ||
3217 | print "Action:", action -- prints: "view" | ||
3218 | </pre> | ||
3219 | </YueDisplay> | ||
3220 | |||
2785 | ## Object Oriented Programming | 3221 | ## Object Oriented Programming |
2786 | 3222 | ||
2787 | 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. | 3223 | 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. |
@@ -2913,7 +3349,7 @@ class BackPack extends Inventory | |||
2913 | 3349 | ||
2914 | Here we extend our Inventory class, and limit the amount of items it can carry. | 3350 | Here we extend our Inventory class, and limit the amount of items it can carry. |
2915 | 3351 | ||
2916 | In this example, we donβt define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. | 3352 | In this example, we don't define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. |
2917 | 3353 | ||
2918 | Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. | 3354 | Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. |
2919 | 3355 | ||
@@ -3000,13 +3436,13 @@ print BackPack.size -- prints 10 | |||
3000 | 3436 | ||
3001 | The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. | 3437 | The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. |
3002 | 3438 | ||
3003 | The class object can be called like a function in order to create new instances. Thatβs how we created instances of classes in the examples above. | 3439 | The class object can be called like a function in order to create new instances. That's how we created instances of classes in the examples above. |
3004 | 3440 | ||
3005 | A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. | 3441 | A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. |
3006 | 3442 | ||
3007 | The class objectβs metatable reads properties from the base if they donβt exist in the class object. This means we can access functions and properties directly from the class. | 3443 | The class object's metatable reads properties from the base if they don't exist in the class object. This means we can access functions and properties directly from the class. |
3008 | 3444 | ||
3009 | It is important to note that assigning to the class object does not assign into the base, so itβs not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. | 3445 | It is important to note that assigning to the class object does not assign into the base, so it's not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. |
3010 | 3446 | ||
3011 | The class object has a couple special properties: | 3447 | The class object has a couple special properties: |
3012 | 3448 | ||
@@ -3079,7 +3515,7 @@ print Counter.count -- prints 2 | |||
3079 | </pre> | 3515 | </pre> |
3080 | </YueDisplay> | 3516 | </YueDisplay> |
3081 | 3517 | ||
3082 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Luaβs colon syntax. | 3518 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax. |
3083 | 3519 | ||
3084 | ```moonscript | 3520 | ```moonscript |
3085 | @@hello 1,2,3,4 | 3521 | @@hello 1,2,3,4 |
@@ -3094,7 +3530,7 @@ The calling semantics of @@ are similar to @. Calling a @@ name will pass the cl | |||
3094 | 3530 | ||
3095 | In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. | 3531 | In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. |
3096 | 3532 | ||
3097 | Here is an alternative way to create a class variable compared to whatβs described above: | 3533 | Here is an alternative way to create a class variable compared to what's described above: |
3098 | 3534 | ||
3099 | ```moonscript | 3535 | ```moonscript |
3100 | class Things | 3536 | class Things |
@@ -3360,19 +3796,19 @@ In this usage, with can be seen as a special form of the K combinator. | |||
3360 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. | 3796 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. |
3361 | 3797 | ||
3362 | ```moonscript | 3798 | ```moonscript |
3363 | with str = "Hello" | 3799 | with str := "Hello" |
3364 | print "original:", str | 3800 | print "original:", str |
3365 | print "upper:", \upper! | 3801 | print "upper:", \upper! |
3366 | ``` | 3802 | ``` |
3367 | <YueDisplay> | 3803 | <YueDisplay> |
3368 | <pre> | 3804 | <pre> |
3369 | with str = "Hello" | 3805 | with str := "Hello" |
3370 | print "original:", str | 3806 | print "original:", str |
3371 | print "upper:", \upper! | 3807 | print "upper:", \upper! |
3372 | </pre> | 3808 | </pre> |
3373 | </YueDisplay> | 3809 | </YueDisplay> |
3374 | 3810 | ||
3375 | Accessing special keys with `[]` in a `with` statement. | 3811 | You can access special keys with `[]` in a `with` statement. |
3376 | 3812 | ||
3377 | ```moonscript | 3813 | ```moonscript |
3378 | with tb | 3814 | with tb |
@@ -3395,6 +3831,18 @@ with tb | |||
3395 | </pre> | 3831 | </pre> |
3396 | </YueDisplay> | 3832 | </YueDisplay> |
3397 | 3833 | ||
3834 | `with?` is an enhanced version of `with` syntax, which introduces an existential check to safely access objects that may be nil without explicit null checks. | ||
3835 | |||
3836 | ```moonscript | ||
3837 | with? obj | ||
3838 | print obj.name | ||
3839 | ``` | ||
3840 | <YueDisplay> | ||
3841 | <pre> | ||
3842 | with? obj | ||
3843 | print obj.name | ||
3844 | </pre> | ||
3845 | </YueDisplay> | ||
3398 | 3846 | ||
3399 | ## Do | 3847 | ## Do |
3400 | 3848 | ||
@@ -3415,7 +3863,7 @@ print var -- nil here | |||
3415 | </pre> | 3863 | </pre> |
3416 | </YueDisplay> | 3864 | </YueDisplay> |
3417 | 3865 | ||
3418 | YueScriptβs **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. | 3866 | YueScript's **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. |
3419 | 3867 | ||
3420 | ```moonscript | 3868 | ```moonscript |
3421 | counter = do | 3869 | counter = do |
@@ -3541,7 +3989,7 @@ print i -- will print 0 | |||
3541 | </pre> | 3989 | </pre> |
3542 | </YueDisplay> | 3990 | </YueDisplay> |
3543 | 3991 | ||
3544 | In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isnβt clear what names have already been declared. | 3992 | In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn't clear what names have already been declared. |
3545 | 3993 | ||
3546 | It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. | 3994 | It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. |
3547 | 3995 | ||
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md index 1a2da96..15f4768 100755 --- a/doc/docs/zh/doc/README.md +++ b/doc/docs/zh/doc/README.md | |||
@@ -16,19 +16,29 @@ YueοΌζοΌζ―δΈζδΈβζδΊβηεη§°γ | |||
16 | ### ζδΉθζ¬ζ¦θ§ | 16 | ### ζδΉθζ¬ζ¦θ§ |
17 | ```moonscript | 17 | ```moonscript |
18 | -- ε―Όε ₯θ―ζ³ | 18 | -- ε―Όε ₯θ―ζ³ |
19 | import "yue" as :p, :to_lua | 19 | import p, to_lua from "yue" |
20 | 20 | ||
21 | -- ιεΌε―Ήθ±‘ | 21 | -- ιεΌε―Ήθ±‘ |
22 | inventory = | 22 | inventory = |
23 | equipment: | 23 | equipment: |
24 | * "sword" | 24 | - "sword" |
25 | * "shield" | 25 | - "shield" |
26 | items: | 26 | items: |
27 | * name: "potion" | 27 | - name: "potion" |
28 | count: 10 | 28 | count: 10 |
29 | * name: "bread" | 29 | - name: "bread" |
30 | count: 3 | 30 | count: 3 |
31 | 31 | ||
32 | -- ε葨ζ¨ε―Ό | ||
33 | map = (arr, action) -> | ||
34 | [action item for item in *arr] | ||
35 | |||
36 | filter = (arr, cond) -> | ||
37 | [item for item in *arr when cond item] | ||
38 | |||
39 | reduce = (arr, init, action): init -> | ||
40 | init = action init, item for item in *arr | ||
41 | |||
32 | -- η‘ιζδ½η¬¦ | 42 | -- η‘ιζδ½η¬¦ |
33 | [1, 2, 3] | 43 | [1, 2, 3] |
34 | |> map (x) -> x * 2 | 44 | |> map (x) -> x * 2 |
@@ -51,19 +61,29 @@ export π = "ζδΉθζ¬" | |||
51 | <YueDisplay> | 61 | <YueDisplay> |
52 | <pre> | 62 | <pre> |
53 | -- ε―Όε ₯θ―ζ³ | 63 | -- ε―Όε ₯θ―ζ³ |
54 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
55 | 65 | ||
56 | -- ιεΌε―Ήθ±‘ | 66 | -- ιεΌε―Ήθ±‘ |
57 | inventory = | 67 | inventory = |
58 | equipment: | 68 | equipment: |
59 | * "sword" | 69 | - "sword" |
60 | * "shield" | 70 | - "shield" |
61 | items: | 71 | items: |
62 | * name: "potion" | 72 | - name: "potion" |
63 | count: 10 | 73 | count: 10 |
64 | * name: "bread" | 74 | - name: "bread" |
65 | count: 3 | 75 | count: 3 |
66 | 76 | ||
77 | -- ε葨ζ¨ε―Ό | ||
78 | map = (arr, action) -> | ||
79 | [action item for item in *arr] | ||
80 | |||
81 | filter = (arr, cond) -> | ||
82 | [item for item in *arr when cond item] | ||
83 | |||
84 | reduce = (arr, init, action): init -> | ||
85 | init = action init, item for item in *arr | ||
86 | |||
67 | -- η‘ιζδ½η¬¦ | 87 | -- η‘ιζδ½η¬¦ |
68 | [1, 2, 3] | 88 | [1, 2, 3] |
69 | |> map (x) -> x * 2 | 89 | |> map (x) -> x * 2 |
@@ -122,7 +142,7 @@ export π = "ζδΉθζ¬" | |||
122 | 142 | ||
123 | * **δΈθ½½ι’ηΌθ―ηδΊθΏεΆη¨εΊ** | 143 | * **δΈθ½½ι’ηΌθ―ηδΊθΏεΆη¨εΊ** |
124 | 144 | ||
125 |  ζ¨ε―δ»₯δΈθ½½ι’ηΌθ―ηδΊθΏεΆη¨εΊοΌε ζ¬ε ΌεΉδΈε Lua ηζ¬ηδΊθΏεΆε―ζ§θ‘ζδ»ΆεεΊζδ»Άγ | 145 |  δ½ ε―δ»₯δΈθ½½ι’ηΌθ―ηδΊθΏεΆη¨εΊοΌε ζ¬ε ΌεΉδΈε Lua ηζ¬ηδΊθΏεΆε―ζ§θ‘ζδ»ΆεεΊζδ»Άγ |
126 | 146 | ||
127 |  ε¨[θΏι](https://github.com/IppClub/YueScript/releases)δΈθ½½ι’ηΌθ―ηδΊθΏεΆη¨εΊγ | 147 |  ε¨[θΏι](https://github.com/IppClub/YueScript/releases)δΈθ½½ι’ηΌθ―ηδΊθΏεΆη¨εΊγ |
128 | 148 | ||
@@ -132,14 +152,14 @@ export π = "ζδΉθζ¬" | |||
132 | 152 | ||
133 | ε¨LuaδΈδ½Ώη¨ζδΉθζ¬ζ¨‘εοΌ | 153 | ε¨LuaδΈδ½Ώη¨ζδΉθζ¬ζ¨‘εοΌ |
134 | 154 | ||
135 | * **η¨ζ³ 1** | 155 | * **η¨ζ³ 1** |
136 | ε¨LuaδΈεΌε ₯ "δ½ ηθζ¬ε ₯ε£ζδ»Ά.yue"γ | 156 | ε¨LuaδΈεΌε ₯ "δ½ ηθζ¬ε ₯ε£ζδ»Ά.yue"γ |
137 | ```Lua | 157 | ```Lua |
138 | require("yue")("δ½ ηθζ¬ε ₯ε£ζδ»Ά") | 158 | require("yue")("δ½ ηθζ¬ε ₯ε£ζδ»Ά") |
139 | ``` | 159 | ``` |
140 | ε½δ½ ε¨εδΈθ·―εΎδΈζ "δ½ ηθζ¬ε ₯ε£ζδ»Ά.yue" ηΌθ―ζδΊ "δ½ ηθζ¬ε ₯ε£ζδ»Ά.lua" ζΆοΌδ»ηΆε―δ»₯δ½Ώη¨θΏδΈͺ代η ε θ½½ .lua 代η ζδ»Άγε¨ε Άδ½ηζδΉθζ¬ζδ»ΆδΈοΌεͺιζ£εΈΈδ½Ώη¨ **require** ζ **import**θΏθ‘θζ¬εΌη¨ε³ε―γιθ――ζΆζ―δΈη代η θ‘ε·δΉδΌθ’«ζ£η‘ε€ηγ | 160 | ε½δ½ ε¨εδΈθ·―εΎδΈζ "δ½ ηθζ¬ε ₯ε£ζδ»Ά.yue" ηΌθ―ζδΊ "δ½ ηθζ¬ε ₯ε£ζδ»Ά.lua" ζΆοΌδ»ηΆε―δ»₯δ½Ώη¨θΏδΈͺ代η ε θ½½ .lua 代η ζδ»Άγε¨ε Άδ½ηζδΉθζ¬ζδ»ΆδΈοΌεͺιζ£εΈΈδ½Ώη¨ **require** ζ **import**θΏθ‘θζ¬εΌη¨ε³ε―γιθ――ζΆζ―δΈη代η θ‘ε·δΉδΌθ’«ζ£η‘ε€ηγ |
141 | 161 | ||
142 | * **η¨ζ³ 2** | 162 | * **η¨ζ³ 2** |
143 | ζε¨εΌε ₯ζδΉθζ¬ζ¨‘εεΉΆιειθ――ζΆζ―ζ₯εΈε©θ°θ―γ | 163 | ζε¨εΌε ₯ζδΉθζ¬ζ¨‘εεΉΆιειθ――ζΆζ―ζ₯εΈε©θ°θ―γ |
144 | ```lua | 164 | ```lua |
145 | local yue = require("yue") | 165 | local yue = require("yue") |
@@ -151,7 +171,7 @@ end, function(err) | |||
151 | end) | 171 | end) |
152 | ``` | 172 | ``` |
153 | 173 | ||
154 | * **η¨ζ³ 3** | 174 | * **η¨ζ³ 3** |
155 | ε¨LuaδΈδ½Ώη¨ζδΉθζ¬ηΌθ―ε¨εθ½γ | 175 | ε¨LuaδΈδ½Ώη¨ζδΉθζ¬ηΌθ―ε¨εθ½γ |
156 | ```lua | 176 | ```lua |
157 | local yue = require("yue") | 177 | local yue = require("yue") |
@@ -202,12 +222,12 @@ f! | |||
202 | δΈζ·»ε δ»»δ½ιι‘Ήζ§θ‘ε½δ»€ε―δ»₯θΏε ₯REPL樑εΌοΌ | 222 | δΈζ·»ε δ»»δ½ιι‘Ήζ§θ‘ε½δ»€ε―δ»₯θΏε ₯REPL樑εΌοΌ |
203 | ε¨εθ‘θΎε ₯η¬¦ε· '$' εΉΆζ’θ‘εοΌε―δ»₯εΌε§ζζ―εζ’ε€θ‘θΎε ₯ζ¨‘εΌ | 223 | ε¨εθ‘θΎε ₯η¬¦ε· '$' εΉΆζ’θ‘εοΌε―δ»₯εΌε§ζζ―εζ’ε€θ‘θΎε ₯ζ¨‘εΌ |
204 | ``` | 224 | ``` |
205 |   δ½Ώη¨ζ‘δΎοΌ | 225 |   δ½Ώη¨ζ‘δΎοΌ |
206 |   ιε½ηΌθ―ε½εθ·―εΎδΈζ©ε±εδΈΊ **.yue** ηζ―δΈͺζδΉθζ¬ζδ»ΆοΌ **yue .** | 226 |   ιε½ηΌθ―ε½εθ·―εΎδΈζ©ε±εδΈΊ **.yue** ηζ―δΈͺζδΉθζ¬ζδ»ΆοΌ **yue .** |
207 |   ηΌθ―εΉΆε°η»ζδΏεε°ηζ θ·―εΎοΌ **yue -t /target/path/ .** | 227 |   ηΌθ―εΉΆε°η»ζδΏεε°ηζ θ·―εΎοΌ **yue -t /target/path/ .** |
208 |   ηΌθ―εΉΆδΏηθ°θ―δΏ‘ζ―οΌ **yue -l .** | 228 |   ηΌθ―εΉΆδΏηθ°θ―δΏ‘ζ―οΌ **yue -l .** |
209 |   ηΌθ―εΉΆηζε缩代η οΌ **yue -m .** | 229 |   ηΌθ―εΉΆηζε缩代η οΌ **yue -m .** |
210 |   η΄ζ₯ζ§θ‘代η οΌ **yue -e 'print 123'** | 230 |   η΄ζ₯ζ§θ‘代η οΌ **yue -e 'print 123'** |
211 |   ζ§θ‘δΈδΈͺζδΉθζ¬ζδ»ΆοΌ **yue -e main.yue** | 231 |   ζ§θ‘δΈδΈͺζδΉθζ¬ζδ»ΆοΌ **yue -e main.yue** |
212 | 232 | ||
213 | ## ε | 233 | ## ε |
@@ -333,7 +353,7 @@ end | |||
333 | 353 | ||
334 | ### ε―ΌεΊε | 354 | ### ε―ΌεΊε |
335 | 355 | ||
336 | εε½ζ°ε―δ»₯δ»δΈδΈͺ樑εδΈε―ΌεΊοΌεΉΆε¨ε¦δΈδΈͺ樑εδΈε―Όε ₯γζ¨εΏ ι‘»ε°ε―ΌεΊηεε½ζ°ζΎε¨δΈδΈͺεη¬ηζδ»ΆδΈδ½Ώη¨οΌθδΈεͺζεεδΉγεε―Όε ₯εεε±εΌε―δ»₯ζΎε ₯θΏδΈͺεε―ΌεΊζ¨‘εδΈγ | 356 | εε½ζ°ε―δ»₯δ»δΈδΈͺ樑εδΈε―ΌεΊοΌεΉΆε¨ε¦δΈδΈͺ樑εδΈε―Όε ₯γδ½ εΏ ι‘»ε°ε―ΌεΊηεε½ζ°ζΎε¨δΈδΈͺεη¬ηζδ»ΆδΈδ½Ώη¨οΌθδΈεͺζεεδΉγεε―Όε ₯εεε±εΌε―δ»₯ζΎε ₯θΏδΈͺεε―ΌεΊζ¨‘εδΈγ |
337 | ```moonscript | 357 | ```moonscript |
338 | -- ζδ»Ά: utils.yue | 358 | -- ζδ»Ά: utils.yue |
339 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | 359 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" |
@@ -422,6 +442,54 @@ print "ζζηζδΈΎη±»ε:", $BodyType Static | |||
422 | </pre> | 442 | </pre> |
423 | </YueDisplay> | 443 | </YueDisplay> |
424 | 444 | ||
445 | ### εεζ°ζ£ζ₯ | ||
446 | |||
447 | ε―δ»₯η΄ζ₯ε¨εζ°ε葨δΈε£°ζζζη AST θηΉη±»εοΌεΉΆε¨ηΌθ―ζΆζ£ζ₯δΌ ε ₯ηεεζ°ζ―ε¦η¬¦ει’ζγ | ||
448 | |||
449 | ```moonscript | ||
450 | macro printNumAndStr = (num `Num, str `String) -> | | ||
451 | print( | ||
452 | #{num} | ||
453 | #{str} | ||
454 | ) | ||
455 | |||
456 | $printNumAndStr 123, "hello" | ||
457 | ``` | ||
458 | <YueDisplay> | ||
459 | <pre> | ||
460 | macro printNumAndStr = (num `Num, str `String) -> | | ||
461 | print( | ||
462 | #{num} | ||
463 | #{str} | ||
464 | ) | ||
465 | |||
466 | $printNumAndStr 123, "hello" | ||
467 | </pre> | ||
468 | </YueDisplay> | ||
469 | |||
470 | ε¦ζιθ¦εζ΄ε η΅ζ΄»ηεζ°ζ£ζ₯ζδ½οΌε―δ»₯δ½Ώη¨ε η½η `$is_ast` εε½ζ°ε¨ειηδ½η½θΏθ‘ζε¨ζ£ζ₯γ | ||
471 | |||
472 | ```moonscript | ||
473 | macro printNumAndStr = (num, str) -> | ||
474 | error "expected Num as first argument" unless $is_ast Num, num | ||
475 | error "expected String as second argument" unless $is_ast String, str | ||
476 | "print(#{num}, #{str})" | ||
477 | |||
478 | $printNumAndStr 123, "hello" | ||
479 | ``` | ||
480 | <YueDisplay> | ||
481 | <pre> | ||
482 | macro printNumAndStr = (num, str) -> | ||
483 | error "expected Num as first argument" unless $is_ast Num, num | ||
484 | error "expected String as second argument" unless $is_ast String, str | ||
485 | "print(#{num}, #{str})" | ||
486 | |||
487 | $printNumAndStr 123, "hello" | ||
488 | </pre> | ||
489 | </YueDisplay> | ||
490 | |||
491 | ζ΄ε€ε ³δΊε―η¨ AST θηΉηθ―¦η»δΏ‘ζ―οΌθ―·εθ [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) δΈε€§εηθ§εεδΉγ | ||
492 | |||
425 | ## ζδ½η¬¦ | 493 | ## ζδ½η¬¦ |
426 | 494 | ||
427 | LuaηζζδΊε εδΈε ζδ½η¬¦ε¨ζδΉθζ¬δΈι½ζ―ε―η¨ηγζ€ε€οΌ**!=** 符ε·ζ― **~=** ηε«εοΌθ **\\** ζ **::** εε―η¨δΊηΌειΎεΌε½ζ°θ°η¨οΌε¦εδ½ `tb\func!` ζ `tb::func!`γζ€ε€ζδΉθζ¬θΏζδΎδΊδΈδΊε Άδ»ηΉζηζδ½η¬¦οΌδ»₯ηΌεζ΄ε ·θ‘¨θΎΎεη代η γ | 495 | LuaηζζδΊε εδΈε ζδ½η¬¦ε¨ζδΉθζ¬δΈι½ζ―ε―η¨ηγζ€ε€οΌ**!=** 符ε·ζ― **~=** ηε«εοΌθ **\\** ζ **::** εε―η¨δΊηΌειΎεΌε½ζ°θ°η¨οΌε¦εδ½ `tb\func!` ζ `tb::func!`γζ€ε€ζδΉθζ¬θΏζδΎδΊδΈδΊε Άδ»ηΉζηζδ½η¬¦οΌδ»₯ηΌεζ΄ε ·θ‘¨θΎΎεη代η γ |
@@ -439,7 +507,7 @@ tb::func! if tb != nil | |||
439 | 507 | ||
440 | ### ιΎεΌζ―θΎ | 508 | ### ιΎεΌζ―θΎ |
441 | 509 | ||
442 | ζ¨ε―δ»₯ε¨ζδΉθζ¬δΈθΏθ‘ζ―θΎθ‘¨θΎΎεΌηιΎεΌδΉ¦εοΌ | 510 | δ½ ε―δ»₯ε¨ζδΉθζ¬δΈθΏθ‘ζ―θΎθ‘¨θΎΎεΌηιΎεΌδΉ¦εοΌ |
443 | 511 | ||
444 | ```moonscript | 512 | ```moonscript |
445 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | 513 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 |
@@ -528,7 +596,7 @@ tab[] = "Value" | |||
528 | 596 | ||
529 | ### 葨ζ©ε± | 597 | ### 葨ζ©ε± |
530 | 598 | ||
531 | ζ¨ε―δ»₯δ½Ώη¨εη½ `...` ζδ½η¬¦ε¨Lua葨δΈζε ₯ζ°η»θ‘¨ζεεΈθ‘¨γ | 599 | δ½ ε―δ»₯δ½Ώη¨εη½ `...` ζδ½η¬¦ε¨Lua葨δΈζε ₯ζ°η»θ‘¨ζεεΈθ‘¨γ |
532 | 600 | ||
533 | ```moonscript | 601 | ```moonscript |
534 | parts = | 602 | parts = |
@@ -565,11 +633,26 @@ merge = {...a, ...b} | |||
565 | </pre> | 633 | </pre> |
566 | </YueDisplay> | 634 | </YueDisplay> |
567 | 635 | ||
636 | ### 葨εεη΄’εΌ | ||
637 | |||
638 | δ½ ε―δ»₯δ½Ώη¨ **#** ζδ½η¬¦ζ₯εεη΄’εΌθ‘¨δΈηε η΄ γ | ||
639 | |||
640 | ```moonscript | ||
641 | last = data.items[#] | ||
642 | second_last = data.items[#-1] | ||
643 | ``` | ||
644 | <YueDisplay> | ||
645 | <pre> | ||
646 | last = data.items[#] | ||
647 | second_last = data.items[#-1] | ||
648 | </pre> | ||
649 | </YueDisplay> | ||
650 | |||
568 | ### ε 葨 | 651 | ### ε 葨 |
569 | 652 | ||
570 | **<>** ζδ½η¬¦ε―ζδΎε 葨ζδ½ηεΏ«ζ·ζΉεΌγ | 653 | **<>** ζδ½η¬¦ε―ζδΎε 葨ζδ½ηεΏ«ζ·ζΉεΌγ |
571 | 654 | ||
572 | * **ε 葨εε»Ί** | 655 | * **ε 葨εε»Ί** |
573 | δ½Ώη¨η©Ίζ¬ε· **<>** ζθ’« **<>** ε ε΄ηε ζΉζ³ιεε»ΊζιηLua葨γ | 656 | δ½Ώη¨η©Ίζ¬ε· **<>** ζθ’« **<>** ε ε΄ηε ζΉζ³ιεε»ΊζιηLua葨γ |
574 | 657 | ||
575 | ```moonscript | 658 | ```moonscript |
@@ -605,7 +688,7 @@ close _ = <close>: -> print "θΆ εΊθε΄" | |||
605 | </pre> | 688 | </pre> |
606 | </YueDisplay> | 689 | </YueDisplay> |
607 | 690 | ||
608 | * **ε 葨θΏι** | 691 | * **ε 葨θΏι** |
609 | δ½Ώη¨ **<>** ζθ’« **<>** ε ε΄ηε ζΉζ³εζε¨ **<>** δΈηΌεζδΊθ‘¨θΎΎεΌζ₯θΏιε 葨γ | 692 | δ½Ώη¨ **<>** ζθ’« **<>** ε ε΄ηε ζΉζ³εζε¨ **<>** δΈηΌεζδΊθ‘¨θΎΎεΌζ₯θΏιε 葨γ |
610 | 693 | ||
611 | ```moonscript | 694 | ```moonscript |
@@ -629,7 +712,7 @@ print tb.item | |||
629 | </pre> | 712 | </pre> |
630 | </YueDisplay> | 713 | </YueDisplay> |
631 | 714 | ||
632 | * **ε 葨解ζ** | 715 | * **ε 葨解ζ** |
633 | δ½Ώη¨θ’« **<>** ε ε΄ηε ζΉζ³ιθ§£ζε 葨γ | 716 | δ½Ώη¨θ’« **<>** ε ε΄ηε ζΉζ³ιθ§£ζε 葨γ |
634 | 717 | ||
635 | ```moonscript | 718 | ```moonscript |
@@ -680,7 +763,7 @@ with? io.open "test.txt", "w" | |||
680 | 763 | ||
681 | ### η‘ι | 764 | ### η‘ι |
682 | 765 | ||
683 | δΈε Άδ½Ώη¨δΈη³»εε΅ε₯ηε½ζ°θ°η¨οΌζ¨θΏε―δ»₯θθδ½Ώη¨θΏη符 **|>** ζ₯δΌ ιεΌγ | 766 | δΈε Άδ½Ώη¨δΈη³»εε΅ε₯ηε½ζ°θ°η¨οΌδ½ θΏε―δ»₯θθδ½Ώη¨θΏη符 **|>** ζ₯δΌ ιεΌγ |
684 | 767 | ||
685 | ```moonscript | 768 | ```moonscript |
686 | "δ½ ε₯½" |> print | 769 | "δ½ ε₯½" |> print |
@@ -731,67 +814,87 @@ a ??= false | |||
731 | 814 | ||
732 | ### ιεΌε―Ήθ±‘ | 815 | ### ιεΌε―Ήθ±‘ |
733 | 816 | ||
734 | ζ¨ε―δ»₯ε¨θ‘¨ζ Όεε δ½Ώη¨η¬¦ε· **\*** εΌε§ηΌεδΈη³»ειεΌη»ζγε¦ζζ¨ζ£ε¨εε»ΊιεΌε―Ήθ±‘οΌε―Ήθ±‘ηεζ΅εΏ ι‘»ε ·ζηΈεηηΌ©θΏγ | 817 | δ½ ε―δ»₯ε¨θ‘¨ζ Όεε δ½Ώη¨η¬¦ε· **\*** ζζ― **-** εΌε§ηΌεδΈη³»ειεΌη»ζγε¦ζδ½ ζ£ε¨εε»ΊιεΌε―Ήθ±‘οΌε―Ήθ±‘ηεζ΅εΏ ι‘»ε ·ζηΈεηηΌ©θΏγ |
818 | |||
735 | ```moonscript | 819 | ```moonscript |
820 | -- θ΅εΌζΆδ½Ώη¨ιεΌε―Ήθ±‘ | ||
736 | list = | 821 | list = |
737 | * 1 | 822 | * 1 |
738 | * 2 | 823 | * 2 |
739 | * 3 | 824 | * 3 |
740 | 825 | ||
826 | -- ε½ζ°θ°η¨ζΆδ½Ώη¨ιεΌε―Ήθ±‘ | ||
741 | func | 827 | func |
742 | * 1 | 828 | * 1 |
743 | * 2 | 829 | * 2 |
744 | * 3 | 830 | * 3 |
745 | 831 | ||
832 | -- θΏεζΆδ½Ώη¨ιεΌε―Ήθ±‘ | ||
833 | f = -> | ||
834 | return | ||
835 | * 1 | ||
836 | * 2 | ||
837 | * 3 | ||
838 | |||
839 | -- θ‘¨ζ ΌζΆδ½Ώη¨ιεΌε―Ήθ±‘ | ||
746 | tb = | 840 | tb = |
747 | name: "abc" | 841 | name: "abc" |
748 | 842 | ||
749 | values: | 843 | values: |
750 | * "a" | 844 | - "a" |
751 | * "b" | 845 | - "b" |
752 | * "c" | 846 | - "c" |
753 | 847 | ||
754 | objects: | 848 | objects: |
755 | * name: "a" | 849 | - name: "a" |
756 | value: 1 | 850 | value: 1 |
757 | func: => @value + 1 | 851 | func: => @value + 1 |
758 | tb: | 852 | tb: |
759 | fieldA: 1 | 853 | fieldA: 1 |
760 | 854 | ||
761 | * name: "b" | 855 | - name: "b" |
762 | value: 2 | 856 | value: 2 |
763 | func: => @value + 2 | 857 | func: => @value + 2 |
764 | tb: { } | 858 | tb: { } |
765 | |||
766 | ``` | 859 | ``` |
767 | <YueDisplay> | 860 | <YueDisplay> |
768 | <pre> | 861 | <pre> |
862 | -- θ΅εΌζΆδ½Ώη¨ιεΌε―Ήθ±‘ | ||
769 | list = | 863 | list = |
770 | * 1 | 864 | * 1 |
771 | * 2 | 865 | * 2 |
772 | * 3 | 866 | * 3 |
773 | 867 | ||
868 | -- ε½ζ°θ°η¨ζΆδ½Ώη¨ιεΌε―Ήθ±‘ | ||
774 | func | 869 | func |
775 | * 1 | 870 | * 1 |
776 | * 2 | 871 | * 2 |
777 | * 3 | 872 | * 3 |
778 | 873 | ||
874 | -- θΏεζΆδ½Ώη¨ιεΌε―Ήθ±‘ | ||
875 | f = -> | ||
876 | return | ||
877 | * 1 | ||
878 | * 2 | ||
879 | * 3 | ||
880 | |||
881 | -- θ‘¨ζ ΌζΆδ½Ώη¨ιεΌε―Ήθ±‘ | ||
779 | tb = | 882 | tb = |
780 | name: "abc" | 883 | name: "abc" |
781 | 884 | ||
782 | values: | 885 | values: |
783 | * "a" | 886 | - "a" |
784 | * "b" | 887 | - "b" |
785 | * "c" | 888 | - "c" |
786 | 889 | ||
787 | objects: | 890 | objects: |
788 | * name: "a" | 891 | - name: "a" |
789 | value: 1 | 892 | value: 1 |
790 | func: => @value + 1 | 893 | func: => @value + 1 |
791 | tb: | 894 | tb: |
792 | fieldA: 1 | 895 | fieldA: 1 |
793 | 896 | ||
794 | * name: "b" | 897 | - name: "b" |
795 | value: 2 | 898 | value: 2 |
796 | func: => @value + 2 | 899 | func: => @value + 2 |
797 | tb: { } | 900 | tb: { } |
@@ -859,7 +962,7 @@ do | |||
859 | 962 | ||
860 | ε―ΌεΊθ―ε₯ζδΎδΊδΈη§ηζ΄ηζΉεΌζ₯εδΉε½εη樑εγ | 963 | ε―ΌεΊθ―ε₯ζδΎδΊδΈη§ηζ΄ηζΉεΌζ₯εδΉε½εη樑εγ |
861 | 964 | ||
862 | * **ε½εε―ΌεΊ** | 965 | * **ε½εε―ΌεΊ** |
863 | εΈ¦ε½εηε―ΌεΊε°εδΉδΈδΈͺε±ι¨ειοΌεΉΆε¨ε―ΌεΊη葨δΈζ·»ε δΈδΈͺεεηεζ΅γ | 966 | εΈ¦ε½εηε―ΌεΊε°εδΉδΈδΈͺε±ι¨ειοΌεΉΆε¨ε―ΌεΊη葨δΈζ·»ε δΈδΈͺεεηεζ΅γ |
864 | 967 | ||
865 | ```moonscript | 968 | ```moonscript |
@@ -923,7 +1026,7 @@ export["a-b-c"] = 123 | |||
923 | </pre> | 1026 | </pre> |
924 | </YueDisplay> | 1027 | </YueDisplay> |
925 | 1028 | ||
926 | * **ζͺε½εε―ΌεΊ** | 1029 | * **ζͺε½εε―ΌεΊ** |
927 | ζͺε½εε―ΌεΊδΌε°θ¦ε―ΌεΊηηζ ι‘Ήηζ·»ε ε°ε―ΌεΊθ‘¨ηζ°η»ι¨εγ | 1030 | ζͺε½εε―ΌεΊδΌε°θ¦ε―ΌεΊηηζ ι‘Ήηζ·»ε ε°ε―ΌεΊθ‘¨ηζ°η»ι¨εγ |
928 | 1031 | ||
929 | ```moonscript | 1032 | ```moonscript |
@@ -953,7 +1056,7 @@ export with tmp | |||
953 | </pre> | 1056 | </pre> |
954 | </YueDisplay> | 1057 | </YueDisplay> |
955 | 1058 | ||
956 | * **ι»θ€ε―ΌεΊ** | 1059 | * **ι»θ€ε―ΌεΊ** |
957 | ε¨ε―ΌεΊθ―ε₯δΈδ½Ώη¨ **default** ε ³ιεοΌζ₯ζΏζ’ε―ΌεΊη葨为δΈδΈͺηζ η对豑γ | 1060 | ε¨ε―ΌεΊθ―ε₯δΈδ½Ώη¨ **default** ε ³ιεοΌζ₯ζΏζ’ε―ΌεΊη葨为δΈδΈͺηζ η对豑γ |
958 | 1061 | ||
959 | ```moonscript | 1062 | ```moonscript |
@@ -1223,7 +1326,7 @@ print first, second, color | |||
1223 | </pre> | 1326 | </pre> |
1224 | </YueDisplay> | 1327 | </YueDisplay> |
1225 | 1328 | ||
1226 | ε¨θΏθ‘θ§£ζζΆοΌζ¨ε―δ»₯ζει»θ€εΌοΌε¦οΌ | 1329 | ε¨θΏθ‘θ§£ζζΆοΌδ½ ε―δ»₯ζει»θ€εΌοΌε¦οΌ |
1227 | 1330 | ||
1228 | ```moonscript | 1331 | ```moonscript |
1229 | {:name = "nameless", :job = "jobless"} = person | 1332 | {:name = "nameless", :job = "jobless"} = person |
@@ -1234,7 +1337,7 @@ print first, second, color | |||
1234 | </pre> | 1337 | </pre> |
1235 | </YueDisplay> | 1338 | </YueDisplay> |
1236 | 1339 | ||
1237 | ε¨θΏθ‘ε葨解ζζΆοΌζ¨ε―δ»₯δ½Ώη¨`_`δ½δΈΊε δ½η¬¦οΌ | 1340 | ε¨θΏθ‘ε葨解ζζΆοΌδ½ ε―δ»₯δ½Ώη¨`_`δ½δΈΊε δ½η¬¦οΌ |
1238 | 1341 | ||
1239 | ```moonscript | 1342 | ```moonscript |
1240 | [_, two, _, four] = items | 1343 | [_, two, _, four] = items |
@@ -1245,9 +1348,55 @@ print first, second, color | |||
1245 | </pre> | 1348 | </pre> |
1246 | </YueDisplay> | 1349 | </YueDisplay> |
1247 | 1350 | ||
1248 | ### ε¨ε Άεε°ζΉηθ§£ζ | 1351 | ### θε΄θ§£ζ |
1352 | |||
1353 | δ½ ε―δ»₯δ½Ώη¨ε±εΌθΏη符 `...` ε¨ε葨解ζδΈζ₯ζθ·δΈδΈͺθε΄ηεΌε°εε葨δΈγθΏε¨ε½δ½ ζ³θ¦δ»ε葨ηεΌε€΄εη»ε°ΎζεηΉεε η΄ οΌεζΆζΆιδΈι΄ηε η΄ ζΆιεΈΈζη¨γ | ||
1354 | |||
1355 | ```moonscript | ||
1356 | orders = ["first", "second", "third", "fourth", "last"] | ||
1357 | [first, ...bulk, last] = orders | ||
1358 | print first -- ζε°: first | ||
1359 | print bulk -- ζε°: {"second", "third", "fourth"} | ||
1360 | print last -- ζε°: last | ||
1361 | ``` | ||
1362 | <YueDisplay> | ||
1363 | <pre> | ||
1364 | orders = ["first", "second", "third", "fourth", "last"] | ||
1365 | [first, ...bulk, last] = orders | ||
1366 | print first -- ζε°: first | ||
1367 | print bulk -- ζε°: {"second", "third", "fourth"} | ||
1368 | print last -- ζε°: last | ||
1369 | </pre> | ||
1370 | </YueDisplay> | ||
1371 | |||
1372 | ε±εΌθΏη符ε―δ»₯η¨ε¨δΈεηδ½η½ζ₯ζθ·δΈεηθε΄οΌεΉΆδΈδ½ ε―δ»₯δ½Ώη¨ `_` δ½δΈΊε δ½η¬¦ζ₯θ‘¨η€Ίδ½ ζ³θ·³θΏε―ΉεΊθε΄ηζθ·οΌ | ||
1373 | |||
1374 | ```moonscript | ||
1375 | -- ζθ·η¬¬δΈδΈͺε η΄ δΉεηζζε η΄ | ||
1376 | [first, ...rest] = orders | ||
1377 | |||
1378 | -- ζθ·ζεδΈδΈͺε η΄ δΉεηζζε η΄ | ||
1379 | [...start, last] = orders | ||
1380 | |||
1381 | -- θ·³θΏδΈι΄ηε η΄ οΌεͺζθ·η¬¬δΈδΈͺεζεδΈδΈͺε η΄ | ||
1382 | [first, ..._, last] = orders | ||
1383 | ``` | ||
1384 | <YueDisplay> | ||
1385 | <pre> | ||
1386 | -- ζθ·η¬¬δΈδΈͺε η΄ δΉεηζζε η΄ | ||
1387 | [first, ...rest] = orders | ||
1388 | |||
1389 | -- ζθ·ζεδΈδΈͺε η΄ δΉεηζζε η΄ | ||
1390 | [...start, last] = orders | ||
1391 | |||
1392 | -- θ·³θΏδΈι΄ηε η΄ οΌεͺζθ·η¬¬δΈδΈͺεζεδΈδΈͺε η΄ | ||
1393 | [first, ..._, last] = orders | ||
1394 | </pre> | ||
1395 | </YueDisplay> | ||
1396 | |||
1397 | ### ε¨ε Άεε°ζΉηθ§£ζθ΅εΌ | ||
1249 | 1398 | ||
1250 | θ§£ζδΉε―δ»₯εΊη°ε¨ε ΆειεΌθΏθ‘θ΅εΌηε°ζΉγδΈδΈͺδΎεζ―η¨ε¨forεΎͺη―οΌ | 1399 | θ§£ζθ΅εΌδΉε―δ»₯εΊη°ε¨ε ΆειεΌθΏθ‘θ΅εΌηε°ζΉγδΈδΈͺδΎεζ―η¨ε¨forεΎͺη―δΈοΌ |
1251 | 1400 | ||
1252 | ```moonscript | 1401 | ```moonscript |
1253 | tuples = [ | 1402 | tuples = [ |
@@ -1322,7 +1471,7 @@ print "ε₯½η" | |||
1322 | 1471 | ||
1323 | ### While θ΅εΌ | 1472 | ### While θ΅εΌ |
1324 | 1473 | ||
1325 | ζ¨ε―δ»₯ε¨ while εΎͺη―δΈεζ ·δ½Ώη¨θ΅εΌζ₯θ·εεΎͺη―ζ‘δ»ΆηεΌγ | 1474 | δ½ ε―δ»₯ε¨ while εΎͺη―δΈεζ ·δ½Ώη¨θ΅εΌζ₯θ·εεΎͺη―ζ‘δ»ΆηεΌγ |
1326 | ```moonscript | 1475 | ```moonscript |
1327 | while byte := stream\read_one! | 1476 | while byte := stream\read_one! |
1328 | -- ε―Ή byte εδΈδΊζδ½ | 1477 | -- ε―Ή byte εδΈδΊζδ½ |
@@ -1338,7 +1487,7 @@ while byte := stream\read_one! | |||
1338 | 1487 | ||
1339 | ## ε―εεζ°θ΅εΌ | 1488 | ## ε―εεζ°θ΅εΌ |
1340 | 1489 | ||
1341 | ζ¨ε―δ»₯ε°ε½ζ°θΏεηη»ζθ΅εΌη»δΈδΈͺε―εεζ°η¬¦ε· `...`γηΆεδ½Ώη¨LuaηζΉεΌθΏιε Άε εΉγ | 1490 | δ½ ε―δ»₯ε°ε½ζ°θΏεηη»ζθ΅εΌη»δΈδΈͺε―εεζ°η¬¦ε· `...`γηΆεδ½Ώη¨LuaηζΉεΌθΏιε Άε εΉγ |
1342 | ```moonscript | 1491 | ```moonscript |
1343 | list = [1, 2, 3, 4, 5] | 1492 | list = [1, 2, 3, 4, 5] |
1344 | fn = (ok) -> ok, table.unpack list | 1493 | fn = (ok) -> ok, table.unpack list |
@@ -1360,7 +1509,7 @@ print ok, count, first | |||
1360 | 1509 | ||
1361 | ## η©Ίη½ | 1510 | ## η©Ίη½ |
1362 | 1511 | ||
1363 | ζδΉθζ¬ζ―δΈδΈͺε―Ήη©Ίη½ζζηθ―θ¨γζ¨εΏ ι‘»ε¨ηΈεηηΌ©θΏδΈδ½Ώη¨η©Ίζ Ό **' '** ζεΆθ‘¨η¬¦ **'\t'** ζ₯ηΌεδΈδΊδ»£η εοΌε¦ε½ζ°δ½γεΌε葨εδΈδΊζ§εΆεγε ε«δΈεη©Ίη½η葨达εΌε―θ½ζε³ηδΈεηδΊζ γεΆθ‘¨η¬¦θ’«θ§δΈΊ4δΈͺη©Ίζ ΌοΌδ½ζε₯½δΈθ¦ζ··εδ½Ώη¨η©Ίζ ΌεεΆθ‘¨η¬¦γ | 1512 | ζδΉθζ¬ζ―δΈδΈͺε―Ήη©Ίη½ζζηθ―θ¨γδ½ εΏ ι‘»ε¨ηΈεηηΌ©θΏδΈδ½Ώη¨η©Ίζ Ό **' '** ζεΆθ‘¨η¬¦ **'\t'** ζ₯ηΌεδΈδΊδ»£η εοΌε¦ε½ζ°δ½γεΌε葨εδΈδΊζ§εΆεγε ε«δΈεη©Ίη½η葨达εΌε―θ½ζε³ηδΈεηδΊζ γεΆθ‘¨η¬¦θ’«θ§δΈΊ4δΈͺη©Ίζ ΌοΌδ½ζε₯½δΈθ¦ζ··εδ½Ώη¨η©Ίζ ΌεεΆθ‘¨η¬¦γ |
1364 | 1513 | ||
1365 | ### ε€θ‘ιΎεΌθ°η¨ | 1514 | ### ε€θ‘ιΎεΌθ°η¨ |
1366 | 1515 | ||
@@ -1474,6 +1623,47 @@ catch err | |||
1474 | </pre> | 1623 | </pre> |
1475 | </YueDisplay> | 1624 | </YueDisplay> |
1476 | 1625 | ||
1626 | ### ιθ――ε€ηηε | ||
1627 | |||
1628 | `try?` ζ― `try` ηεθ½ηεθ―ζ³οΌεδΈεθΏε `try` θ―ε₯ηεΈε°ηΆζοΌεΉΆε¨ζεζΆη΄ζ₯θΏε `try` 代η εηη»ζοΌε€±θ΄₯ζΆθΏε `nil` εΌθιι误对豑γ | ||
1629 | |||
1630 | ```moonscript | ||
1631 | a, b, c = try? func! | ||
1632 | |||
1633 | -- δΈη©ΊεΌεεΉΆθΏη符δΈθ΅·δ½Ώη¨ | ||
1634 | a = (try? func!) ?? "default" | ||
1635 | |||
1636 | -- δ½δΈΊε½ζ°εζ° | ||
1637 | f try? func! | ||
1638 | |||
1639 | -- εΈ¦ catch εη try! | ||
1640 | f try? | ||
1641 | print 123 | ||
1642 | func! | ||
1643 | catch e | ||
1644 | print e | ||
1645 | e | ||
1646 | ``` | ||
1647 | <YueDisplay> | ||
1648 | <pre> | ||
1649 | a, b, c = try? func! | ||
1650 | |||
1651 | -- δΈη©ΊεΌεεΉΆθΏη符δΈθ΅·δ½Ώη¨ | ||
1652 | a = (try? func!) ?? "default" | ||
1653 | |||
1654 | -- δ½δΈΊε½ζ°εζ° | ||
1655 | f try? func! | ||
1656 | |||
1657 | -- εΈ¦ catch εη try! | ||
1658 | f try? | ||
1659 | print 123 | ||
1660 | func! | ||
1661 | catch e | ||
1662 | print e | ||
1663 | e | ||
1664 | </pre> | ||
1665 | </YueDisplay> | ||
1666 | |||
1477 | ## ε±ζ§ | 1667 | ## ε±ζ§ |
1478 | 1668 | ||
1479 | ζδΉθζ¬η°ε¨ζδΎδΊLua 5.4ζ°ε’ηε«εε±ζ§ηθ―ζ³ζ―ζγε¨ζδΉθζ¬ηΌθ―ε°ηLuaηζ ηζ¬δ½δΊ5.4ζΆοΌδ½ δ»ηΆε―δ»₯εζΆδ½Ώη¨`const`ε`close`ηε±ζ§ε£°ζθ―ζ³οΌεΉΆθ·εΎεΈΈιζ£ζ₯εδ½η¨εεθ°ηεθ½γ | 1669 | ζδΉθζ¬η°ε¨ζδΎδΊLua 5.4ζ°ε’ηε«εε±ζ§ηθ―ζ³ζ―ζγε¨ζδΉθζ¬ηΌθ―ε°ηLuaηζ ηζ¬δ½δΊ5.4ζΆοΌδ½ δ»ηΆε―δ»₯εζΆδ½Ώη¨`const`ε`close`ηε±ζ§ε£°ζθ―ζ³οΌεΉΆθ·εΎεΈΈιζ£ζ₯εδ½η¨εεθ°ηεθ½γ |
@@ -1502,6 +1692,19 @@ const {:a, :b, c, d} = tb | |||
1502 | </pre> | 1692 | </pre> |
1503 | </YueDisplay> | 1693 | </YueDisplay> |
1504 | 1694 | ||
1695 | δ½ δΉε―δ»₯ε£°ζε ¨ε±ειδΈΊεΈΈιγ | ||
1696 | |||
1697 | ```moonscript | ||
1698 | global const Constant = 123 | ||
1699 | -- Constant = 1 | ||
1700 | ``` | ||
1701 | <YueDisplay> | ||
1702 | <pre> | ||
1703 | global const Constant = 123 | ||
1704 | -- Constant = 1 | ||
1705 | </pre> | ||
1706 | </YueDisplay> | ||
1707 | |||
1505 | ## ει’ι | 1708 | ## ει’ι |
1506 | 1709 | ||
1507 | LuaδΈηζζεΊζ¬ει’ιι½ε―δ»₯ε¨ζδΉθζ¬δΈδ½Ώη¨γε ζ¬ζ°εγε符串γεΈε°εΌε**nil**γ | 1710 | LuaδΈηζζεΊζ¬ει’ιι½ε―δ»₯ε¨ζδΉθζ¬δΈδ½Ώη¨γε ζ¬ζ°εγε符串γεΈε°εΌε**nil**γ |
@@ -1529,17 +1732,78 @@ print "ζζ#{math.random! * 100}%ηζζ‘γ" | |||
1529 | 1732 | ||
1530 | ### ζ°εει’ι | 1733 | ### ζ°εει’ι |
1531 | 1734 | ||
1532 | ζ¨ε―δ»₯ε¨ζ°εει’ιδΈδ½Ώη¨δΈεηΊΏζ₯ε’ε ε―θ―»ζ§γ | 1735 | δ½ ε―δ»₯ε¨ζ°εει’ιδΈδ½Ώη¨δΈεηΊΏζ₯ε’ε ε―θ―»ζ§γ |
1533 | 1736 | ||
1534 | ```moonscript | 1737 | ```moonscript |
1535 | integer = 1_000_000 | 1738 | integer = 1_000_000 |
1536 | hex = 0xEF_BB_BF | 1739 | hex = 0xEF_BB_BF |
1740 | binary = 0B10011 | ||
1537 | ``` | 1741 | ``` |
1538 | <YueDisplay> | 1742 | <YueDisplay> |
1539 | 1743 | ||
1540 | <pre> | 1744 | <pre> |
1541 | integer = 1_000_000 | 1745 | integer = 1_000_000 |
1542 | hex = 0xEF_BB_BF | 1746 | hex = 0xEF_BB_BF |
1747 | binary = 0B10011 | ||
1748 | </pre> | ||
1749 | </YueDisplay> | ||
1750 | |||
1751 | ### YAML ι£ζ Όε符串 | ||
1752 | |||
1753 | δ½Ώη¨ `|` εηΌζ θ°δΈδΈͺε€θ‘ YAML ι£ζ Όεη¬¦δΈ²οΌ | ||
1754 | |||
1755 | ```moonscript | ||
1756 | str = | | ||
1757 | key: value | ||
1758 | list: | ||
1759 | - item1 | ||
1760 | - #{expr} | ||
1761 | ``` | ||
1762 | <YueDisplay> | ||
1763 | <pre> | ||
1764 | str = | | ||
1765 | key: value | ||
1766 | list: | ||
1767 | - item1 | ||
1768 | - #{expr} | ||
1769 | </pre> | ||
1770 | </YueDisplay> | ||
1771 | |||
1772 | ε Άζζη±»δΌΌδΊεη Lua ηε€θ‘ζΌζ₯οΌζζζζ¬οΌε«ζ’θ‘οΌε°θ’«δΏηδΈζ₯οΌεΉΆζ―ζ `#{...}` θ―ζ³οΌιθΏ `tostring(expr)` ζε ₯葨达εΌη»ζγ | ||
1773 | |||
1774 | YAML ι£ζ Όηε€θ‘ε符串δΌθͺε¨ζ£ζ΅ι¦θ‘εζε°ηε ¬ε ±ηΌ©θΏοΌεΉΆδ»ζζθ‘δΈε ι€θ―₯εηΌη©Ίη½ε符γθΏθ©δ½ ε―δ»₯ε¨δ»£η δΈε―Ήι½ζζ¬οΌδ½θΎεΊε符串δΈδΌεΈ¦ε€δ½ηΌ©θΏγ | ||
1775 | |||
1776 | ```moonscript | ||
1777 | fn = -> | ||
1778 | str = | | ||
1779 | foo: | ||
1780 | bar: baz | ||
1781 | return str | ||
1782 | ``` | ||
1783 | <YueDisplay> | ||
1784 | <pre> | ||
1785 | fn = -> | ||
1786 | str = | | ||
1787 | foo: | ||
1788 | bar: baz | ||
1789 | return str | ||
1790 | </pre> | ||
1791 | </YueDisplay> | ||
1792 | |||
1793 | θΎεΊε符串δΈη foo: ε―Ήι½ε°θ‘ι¦οΌδΈδΌεΈ¦ζε½ζ°ηΌ©θΏη©Ίζ ΌγδΏηε ι¨ηΌ©θΏηηΈε―Ήη»ζοΌιεδΉ¦εη»ζεε΅ε₯ζ ·εΌηε εΉγ | ||
1794 | |||
1795 | ζ―ζθͺε¨ε€ηε符δΈηεΌε·γεζζ ηηΉζ符ε·οΌζ ιζε¨θ½¬δΉοΌ | ||
1796 | |||
1797 | ```moonscript | ||
1798 | str = | | ||
1799 | path: "C:\Program Files\App" | ||
1800 | note: 'He said: "#{Hello}!"' | ||
1801 | ``` | ||
1802 | <YueDisplay> | ||
1803 | <pre> | ||
1804 | str = | | ||
1805 | path: "C:\Program Files\App" | ||
1806 | note: 'He said: "#{Hello}!"' | ||
1543 | </pre> | 1807 | </pre> |
1544 | </YueDisplay> | 1808 | </YueDisplay> |
1545 | 1809 | ||
@@ -1644,7 +1908,7 @@ print "ζ°εηεζ―", sum 10, 20 | |||
1644 | </pre> | 1908 | </pre> |
1645 | </YueDisplay> | 1909 | </YueDisplay> |
1646 | 1910 | ||
1647 | ε¦ζζ¨ιθ¦εζΎεΌθΏεοΌε―δ»₯δ½Ώη¨returnε ³ιεοΌ | 1911 | ε¦ζδ½ ιθ¦εζΎεΌθΏεοΌε―δ»₯δ½Ώη¨returnε ³ιεοΌ |
1648 | 1912 | ||
1649 | ```moonscript | 1913 | ```moonscript |
1650 | sum = (x, y) -> return x + y | 1914 | sum = (x, y) -> return x + y |
@@ -1850,7 +2114,7 @@ print @value | |||
1850 | </pre> | 2114 | </pre> |
1851 | </YueDisplay> | 2115 | </YueDisplay> |
1852 | 2116 | ||
1853 | ζ¨ε―δ»₯ιθΏδΈδΈͺε δ½η¬¦ζεεθ°ε½ζ°ηδΌ εδ½η½γ | 2117 | δ½ ε―δ»₯ιθΏδΈδΈͺε δ½η¬¦ζεεθ°ε½ζ°ηδΌ εδ½η½γ |
1854 | 2118 | ||
1855 | ```moonscript | 2119 | ```moonscript |
1856 | (x) <- map _, [1, 2, 3] | 2120 | (x) <- map _, [1, 2, 3] |
@@ -1863,22 +2127,22 @@ x * 2 | |||
1863 | </pre> | 2127 | </pre> |
1864 | </YueDisplay> | 2128 | </YueDisplay> |
1865 | 2129 | ||
1866 | ε¦ζζ¨εΈζε¨εεεθ°ε€ηεη»§η»ηΌεζ΄ε€ε Άεη代η οΌζ¨ε―δ»₯δ½Ώη¨doθ―ε₯ε°δΈε½ε±εεεθ°η代η εεΌγ | 2130 | ε¦ζδ½ εΈζε¨εεεθ°ε€ηεη»§η»ηΌεζ΄ε€ε Άεη代η οΌε―δ»₯δ½Ώη¨ do θ―ε₯ε°δΈε±δΊεεεθ°η代η ειεΌγε―ΉδΊιη²η倴ε½ζ°ηεεεθ°οΌεθ°θΏεεΌηζ¬ε·δΉζ―ε―δ»₯ηη₯ηγ |
1867 | 2131 | ||
1868 | ```moonscript | 2132 | ```moonscript |
1869 | result, msg = do | 2133 | result, msg = do |
1870 | (data) <- readAsync "ζδ»Άε.txt" | 2134 | data <- readAsync "ζδ»Άε.txt" |
1871 | print data | 2135 | print data |
1872 | (info) <- processAsync data | 2136 | info <- processAsync data |
1873 | check info | 2137 | check info |
1874 | print result, msg | 2138 | print result, msg |
1875 | ``` | 2139 | ``` |
1876 | <YueDisplay> | 2140 | <YueDisplay> |
1877 | <pre> | 2141 | <pre> |
1878 | result, msg = do | 2142 | result, msg = do |
1879 | (data) <- readAsync "ζδ»Άε.txt" | 2143 | data <- readAsync "ζδ»Άε.txt" |
1880 | print data | 2144 | print data |
1881 | (info) <- processAsync data | 2145 | info <- processAsync data |
1882 | check info | 2146 | check info |
1883 | print result, msg | 2147 | print result, msg |
1884 | </pre> | 2148 | </pre> |
@@ -2037,7 +2301,7 @@ list_with_one_element = [ 1, ] | |||
2037 | 2301 | ||
2038 | ## ζ¨ε―ΌεΌ | 2302 | ## ζ¨ε―ΌεΌ |
2039 | 2303 | ||
2040 | ζ¨ε―ΌεΌδΈΊζ们ζδΎδΊδΈη§δΎΏζ·ηθ―ζ³οΌιθΏιεη°ζε―Ήθ±‘εΉΆε―Ήε ΆεΌεΊη¨θ‘¨θΎΎεΌζ₯ζι εΊζ°ηθ‘¨ζ ΌγζδΉθζ¬ζδΈ€η§ζ¨ε―ΌεΌοΌε葨ζ¨ε―ΌεΌεθ‘¨ζ Όζ¨ε―ΌεΌγε们ζη»ι½ζ―δΊ§ηLuaθ‘¨ζ ΌοΌε葨ζ¨ε―ΌεΌε°εΌη΄―η§―ε°η±»δΌΌζ°η»ηθ‘¨ζ ΌδΈοΌθθ‘¨ζ Όζ¨ε―ΌεΌε θΈζ¨ε¨ζ―欑ιεζΆθΎη½ζ°θ‘¨ζ ΌηιεεΌγ | 2304 | ζ¨ε―ΌεΌδΈΊζ们ζδΎδΊδΈη§δΎΏζ·ηθ―ζ³οΌιθΏιεη°ζε―Ήθ±‘εΉΆε―Ήε ΆεΌεΊη¨θ‘¨θΎΎεΌζ₯ζι εΊζ°ηθ‘¨ζ ΌγζδΉθζ¬ζδΈ€η§ζ¨ε―ΌεΌοΌε葨ζ¨ε―ΌεΌεθ‘¨ζ Όζ¨ε―ΌεΌγε们ζη»ι½ζ―δΊ§ηLuaθ‘¨ζ ΌοΌε葨ζ¨ε―ΌεΌε°εΌη΄―η§―ε°η±»δΌΌζ°η»ηθ‘¨ζ ΌδΈοΌθθ‘¨ζ Όζ¨ε―ΌεΌε θΈδ½ ε¨ζ―欑ιεζΆθΎη½ζ°θ‘¨ζ ΌηιεεΌγ |
2041 | 2305 | ||
2042 | ### ε葨ζ¨ε―ΌεΌ | 2306 | ### ε葨ζ¨ε―ΌεΌ |
2043 | 2307 | ||
@@ -2057,13 +2321,11 @@ doubled = [item * 2 for i, item in ipairs items] | |||
2057 | ε―δ»₯δ½Ώη¨whenεε₯ηιζ°θ‘¨δΈε ε«ηι‘ΉηοΌ | 2321 | ε―δ»₯δ½Ώη¨whenεε₯ηιζ°θ‘¨δΈε ε«ηι‘ΉηοΌ |
2058 | 2322 | ||
2059 | ```moonscript | 2323 | ```moonscript |
2060 | iter = ipairs items | 2324 | slice = [item for i, item in ipairs items when i > 1 and i < 3] |
2061 | slice = [item for i, item in iter when i > 1 and i < 3] | ||
2062 | ``` | 2325 | ``` |
2063 | <YueDisplay> | 2326 | <YueDisplay> |
2064 | <pre> | 2327 | <pre> |
2065 | iter = ipairs items | 2328 | slice = [item for i, item in ipairs items when i > 1 and i < 3] |
2066 | slice = [item for i, item in iter when i > 1 and i < 3] | ||
2067 | </pre> | 2329 | </pre> |
2068 | </YueDisplay> | 2330 | </YueDisplay> |
2069 | 2331 | ||
@@ -2212,6 +2474,45 @@ slice = [item for item in *items[,,2]] | |||
2212 | </pre> | 2474 | </pre> |
2213 | </YueDisplay> | 2475 | </YueDisplay> |
2214 | 2476 | ||
2477 | ζε°εζε€§θΎΉηι½ε―δ»₯ζ―θ΄ζ°οΌδ½Ώη¨θ΄ζ°ζε³ηθΎΉηζ―δ»θ‘¨ηζ«ε°ΎεΌε§θ‘ηηγ | ||
2478 | |||
2479 | ```moonscript | ||
2480 | -- εζε4δΈͺε η΄ | ||
2481 | slice = [item for item in *items[-4,-1]] | ||
2482 | ``` | ||
2483 | <YueDisplay> | ||
2484 | <pre> | ||
2485 | -- εζε4δΈͺε η΄ | ||
2486 | slice = [item for item in *items[-4,-1]] | ||
2487 | </pre> | ||
2488 | </YueDisplay> | ||
2489 | |||
2490 | εηηζ₯ιΏδΉε―δ»₯ζ―θ΄ζ°οΌθΏζε³ηε η΄ δΌδ»₯ηΈεηι‘ΊεΊθ’«εεΊγ | ||
2491 | |||
2492 | ```moonscript | ||
2493 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2494 | ``` | ||
2495 | <YueDisplay> | ||
2496 | <pre> | ||
2497 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2498 | </pre> | ||
2499 | </YueDisplay> | ||
2500 | |||
2501 | #### εηθ‘¨θΎΎεΌ | ||
2502 | |||
2503 | εηδΉε―δ»₯δ½δΈΊθ‘¨θΎΎεΌζ₯δ½Ώη¨γε―δ»₯η¨δΊθ·εδΈδΈͺ葨ε ε«ηεε葨γ | ||
2504 | |||
2505 | ```moonscript | ||
2506 | -- ε第2ε第4δΈͺε η΄ δ½δΈΊζ°ηε葨 | ||
2507 | sub_list = items[2, 4] | ||
2508 | ``` | ||
2509 | <YueDisplay> | ||
2510 | <pre> | ||
2511 | -- ε第2ε第4δΈͺε η΄ δ½δΈΊζ°ηε葨 | ||
2512 | sub_list = items[2, 4] | ||
2513 | </pre> | ||
2514 | </YueDisplay> | ||
2515 | |||
2215 | ## for εΎͺη― | 2516 | ## for εΎͺη― |
2216 | 2517 | ||
2217 | LuaδΈζδΈ€η§forεΎͺη―ε½’εΌοΌζ°εεειη¨εοΌ | 2518 | LuaδΈζδΈ€η§forεΎͺη―ε½’εΌοΌζ°εεειη¨εοΌ |
@@ -2288,9 +2589,24 @@ doubled_evens = for i = 1, 20 | |||
2288 | </pre> | 2589 | </pre> |
2289 | </YueDisplay> | 2590 | </YueDisplay> |
2290 | 2591 | ||
2291 | ζ¨θΏε―δ»₯η»εforεΎͺη―葨达εΌδΈcontinueθ―ε₯ζ₯θΏζ»€εΌγ | 2592 | ζ€ε€οΌforεΎͺη―θΏζ―ζεΈ¦θΏεεΌηbreakθ―ε₯οΌθΏζ ·εΎͺη―ζ¬θΊ«ε°±ε―δ»₯δ½δΈΊδΈδΈͺ葨达εΌοΌε¨ζ»‘θΆ³ζ‘δ»ΆζΆζειεΊεΉΆθΏεζζδΉηη»ζγ |
2292 | 2593 | ||
2293 | 注ζεΊη°ε¨ε½ζ°δ½ζ«ε°ΎηforεΎͺη―οΌδΈδΌθ’«ε½δ½ζ―δΈδΈͺ葨达εΌοΌεΉΆε°εΎͺη―η»ζη΄―η§―ε°δΈδΈͺε葨δΈδ½δΈΊθΏεεΌοΌηΈεοΌε½ζ°ε°θΏεnilοΌγε¦ζθ¦ε½ζ°ζ«ε°ΎηεΎͺη―转ζ’δΈΊε葨葨达εΌοΌε―δ»₯δ½Ώη¨θΏεθ―ε₯ε forεΎͺη―葨达εΌγ | 2594 | δΎε¦οΌζ₯ζΎη¬¬δΈδΈͺε€§δΊ10ηζ°εοΌ |
2595 | |||
2596 | ```moonscript | ||
2597 | first_large = for n in *numbers | ||
2598 | break n if n > 10 | ||
2599 | ``` | ||
2600 | <YueDisplay> | ||
2601 | <pre> | ||
2602 | first_large = for n in *numbers | ||
2603 | break n if n > 10 | ||
2604 | </pre> | ||
2605 | </YueDisplay> | ||
2606 | |||
2607 | δ½ θΏε―δ»₯η»εforεΎͺη―葨达εΌδΈcontinueθ―ε₯ζ₯θΏζ»€εΌγ | ||
2608 | |||
2609 | 注ζεΊη°ε¨ε½ζ°δ½ζ«ε°ΎηforεΎͺη―οΌδΈδΌθ’«ε½δ½ζ―δΈδΈͺ葨达εΌεΉΆε°εΎͺη―η»ζη΄―η§―ε°δΈδΈͺε葨δΈδ½δΈΊθΏεεΌοΌηΈεοΌε½ζ°ε°θΏεnilοΌγε¦ζθ¦ε½ζ°ζ«ε°ΎηεΎͺη―转ζ’δΈΊε葨葨达εΌοΌε―δ»₯ζΎεΌε°δ½Ώη¨θΏεθ―ε₯ε forεΎͺη―葨达εΌγ | ||
2294 | 2610 | ||
2295 | ```moonscript | 2611 | ```moonscript |
2296 | func_a = -> for i = 1, 10 do print i | 2612 | func_a = -> for i = 1, 10 do print i |
@@ -2515,7 +2831,7 @@ print "δ½ ηεΉΈθΏοΌ" unless math.random! > 0.1 | |||
2515 | 2831 | ||
2516 | ### θε΄θ‘¨θΎΎεΌ | 2832 | ### θε΄θ‘¨θΎΎεΌ |
2517 | 2833 | ||
2518 | ζ¨ε―δ»₯δ½Ώη¨θε΄θ‘¨θΎΎεΌζ₯ηΌεθΏθ‘θε΄ζ£ζ₯η代η γ | 2834 | δ½ ε―δ»₯δ½Ώη¨θε΄θ‘¨θΎΎεΌζ₯ηΌεθΏθ‘θε΄ζ£ζ₯η代η γ |
2519 | 2835 | ||
2520 | ```moonscript | 2836 | ```moonscript |
2521 | a = 5 | 2837 | a = 5 |
@@ -2588,28 +2904,26 @@ reader\parse_line! until reader\eof! | |||
2588 | 2904 | ||
2589 | ## switch θ―ε₯ | 2905 | ## switch θ―ε₯ |
2590 | 2906 | ||
2591 | switchθ―ε₯ζ―δΈΊδΊηεζ£ζ₯δΈη³»εηΈεεΌηifθ―ε₯θζδΎηηεθ―ζ³γθ¦ζ³¨ζη¨δΊζ―θΎζ£ζ₯ηηζ εΌεͺδΌθ‘ηδΈζ¬‘γεifθ―ε₯δΈζ ·οΌswitchθ―ε₯ε¨ζεε―δ»₯ζ₯δΈδΈͺelse代η εζ₯ε€η沑ζεΉι ηζ ε΅γε¨ηζηLua代η δΈοΌθΏθ‘ζ―θΎζ―δ½Ώη¨==ζδ½η¬¦εζηγ | 2907 | switchθ―ε₯ζ―δΈΊδΊηεζ£ζ₯δΈη³»εηΈεεΌηifθ―ε₯θζδΎηηεθ―ζ³γθ¦ζ³¨ζη¨δΊζ―θΎζ£ζ₯ηηζ εΌεͺδΌθ‘ηδΈζ¬‘γεifθ―ε₯δΈζ ·οΌswitchθ―ε₯ε¨ζεε―δ»₯ζ₯δΈδΈͺelse代η εζ₯ε€η沑ζεΉι ηζ ε΅γε¨ηζηLua代η δΈοΌθΏθ‘ζ―θΎζ―δ½Ώη¨==ζδ½η¬¦εζηγswitchθ―ε₯δΈδΉε―δ»₯δ½Ώη¨θ΅εΌθ‘¨θΎΎεΌζ₯ε¨εδΈ΄ζΆειεΌγ |
2592 | 2908 | ||
2593 | ```moonscript | 2909 | ```moonscript |
2594 | name = "Dan" | 2910 | switch name := "Dan" |
2595 | switch name | ||
2596 | when "Robert" | 2911 | when "Robert" |
2597 | print "δ½ ζ―Robert" | 2912 | print "δ½ ζ―Robert" |
2598 | when "Dan", "Daniel" | 2913 | when "Dan", "Daniel" |
2599 | print "δ½ ηεεζ―Dan" | 2914 | print "δ½ ηεεζ―Dan" |
2600 | else | 2915 | else |
2601 | print "ζδΈη₯ιδ½ ηεε" | 2916 | print "ζδΈθ€θ―δ½ οΌδ½ ηεεζ―#{name}" |
2602 | ``` | 2917 | ``` |
2603 | <YueDisplay> | 2918 | <YueDisplay> |
2604 | <pre> | 2919 | <pre> |
2605 | name = "Dan" | 2920 | switch name := "Dan" |
2606 | switch name | ||
2607 | when "Robert" | 2921 | when "Robert" |
2608 | print "δ½ ζ―Robert" | 2922 | print "δ½ ζ―Robert" |
2609 | when "Dan", "Daniel" | 2923 | when "Dan", "Daniel" |
2610 | print "δ½ ηεεζ―Dan" | 2924 | print "δ½ ηεεζ―Dan" |
2611 | else | 2925 | else |
2612 | print "ζδΈη₯ιδ½ ηεε" | 2926 | print "ζδΈθ€θ―δ½ οΌδ½ ηεεζ―#{name}" |
2613 | </pre> | 2927 | </pre> |
2614 | </YueDisplay> | 2928 | </YueDisplay> |
2615 | 2929 | ||
@@ -2686,7 +3000,7 @@ else | |||
2686 | </pre> | 3000 | </pre> |
2687 | </YueDisplay> | 3001 | </YueDisplay> |
2688 | 3002 | ||
2689 | εΌεΎζ³¨ζηζ―οΌε¨ηζLua代η ζΆοΌζ们θ¦εζ£ζ₯ηηζ ειδΌζΎε¨==葨达εΌηε³δΎ§γε½ζ¨εΈζη»whenεε₯ηζ―θΎε―Ήθ±‘εδΉδΈδΈͺ\_\_eqε ζΉζ³ζ₯ιθ½½ε€ζι»θΎζΆοΌε―θ½δΌζη¨γ | 3003 | εΌεΎζ³¨ζηζ―οΌε¨ηζLua代η ζΆοΌζ们θ¦εζ£ζ₯ηηζ ειδΌζΎε¨==葨达εΌηε³δΎ§γε½δ½ εΈζη»whenεε₯ηζ―θΎε―Ήθ±‘εδΉδΈδΈͺ\_\_eqε ζΉζ³ζ₯ιθ½½ε€ζι»θΎζΆοΌε―θ½δΌζη¨γ |
2690 | 3004 | ||
2691 | ### θ‘¨ζ ΌεΉι | 3005 | ### θ‘¨ζ ΌεΉι |
2692 | 3006 | ||
@@ -2746,9 +3060,126 @@ switch item | |||
2746 | </pre> | 3060 | </pre> |
2747 | </YueDisplay> | 3061 | </YueDisplay> |
2748 | 3062 | ||
3063 | δ½ δΉε―δ»₯εΉι ζ°η»ε η΄ γθ‘¨ζ Όεζ΅οΌηθ³δ½Ώη¨ζ°η»ζθ‘¨ζ Όει’ιζ₯εΉι ε΅ε₯ηη»ζγ | ||
3064 | |||
3065 | εΉι ζ°η»ε η΄ γ | ||
3066 | |||
3067 | ```moonscript | ||
3068 | switch tb | ||
3069 | when [1, 2, 3] | ||
3070 | print "1, 2, 3" | ||
3071 | when [1, b, 3] | ||
3072 | print "1, #{b}, 3" | ||
3073 | when [1, 2, b = 3] -- ειbζι»θ€εΌ | ||
3074 | print "1, 2, #{b}" | ||
3075 | ``` | ||
3076 | <YueDisplay> | ||
3077 | <pre> | ||
3078 | switch tb | ||
3079 | when [1, 2, 3] | ||
3080 | print "1, 2, 3" | ||
3081 | when [1, b, 3] | ||
3082 | print "1, #{b}, 3" | ||
3083 | when [1, 2, b = 3] -- ειbζι»θ€εΌ | ||
3084 | print "1, 2, #{b}" | ||
3085 | </pre> | ||
3086 | </YueDisplay> | ||
3087 | |||
3088 | εΉι θ‘¨ζ Όεζ΅γ | ||
3089 | |||
3090 | ```moonscript | ||
3091 | switch tb | ||
3092 | when success: true, :result | ||
3093 | print "ζε", result | ||
3094 | when success: false | ||
3095 | print "ε€±θ΄₯", result | ||
3096 | else | ||
3097 | print "ζ ζεΌ" | ||
3098 | ``` | ||
3099 | <YueDisplay> | ||
3100 | <pre> | ||
3101 | switch tb | ||
3102 | when success: true, :result | ||
3103 | print "ζε", result | ||
3104 | when success: false | ||
3105 | print "ε€±θ΄₯", result | ||
3106 | else | ||
3107 | print "ζ ζεΌ" | ||
3108 | </pre> | ||
3109 | </YueDisplay> | ||
3110 | |||
3111 | εΉι ε΅ε₯ηθ‘¨ζ Όη»ζγ | ||
3112 | |||
3113 | ```moonscript | ||
3114 | switch tb | ||
3115 | when data: {type: "success", :content} | ||
3116 | print "ζε", content | ||
3117 | when data: {type: "error", :content} | ||
3118 | print "ε€±θ΄₯", content | ||
3119 | else | ||
3120 | print "ζ ζεΌ" | ||
3121 | ``` | ||
3122 | <YueDisplay> | ||
3123 | <pre> | ||
3124 | switch tb | ||
3125 | when data: {type: "success", :content} | ||
3126 | print "ζε", content | ||
3127 | when data: {type: "error", :content} | ||
3128 | print "ε€±θ΄₯", content | ||
3129 | else | ||
3130 | print "ζ ζεΌ" | ||
3131 | </pre> | ||
3132 | </YueDisplay> | ||
3133 | |||
3134 | εΉι θ‘¨ζ Όζ°η»γ | ||
3135 | |||
3136 | ```moonscript | ||
3137 | switch tb | ||
3138 | when [ | ||
3139 | {a: 1, b: 2} | ||
3140 | {a: 3, b: 4} | ||
3141 | {a: 5, b: 6} | ||
3142 | fourth | ||
3143 | ] | ||
3144 | print "εΉι ζε", fourth | ||
3145 | ``` | ||
3146 | <YueDisplay> | ||
3147 | <pre> | ||
3148 | switch tb | ||
3149 | when [ | ||
3150 | {a: 1, b: 2} | ||
3151 | {a: 3, b: 4} | ||
3152 | {a: 5, b: 6} | ||
3153 | fourth | ||
3154 | ] | ||
3155 | print "εΉι ζε", fourth | ||
3156 | </pre> | ||
3157 | </YueDisplay> | ||
3158 | |||
3159 | εΉι δΈδΈͺε葨幢ζθ·ηΉεθε΄ε ηε η΄ γ | ||
3160 | |||
3161 | ```moonscript | ||
3162 | segments = ["admin", "users", "logs", "view"] | ||
3163 | switch segments | ||
3164 | when [...groups, resource, action] | ||
3165 | print "Group:", groups -- ζε°: {"admin", "users"} | ||
3166 | print "Resource:", resource -- ζε°: "logs" | ||
3167 | print "Action:", action -- ζε°: "view" | ||
3168 | ``` | ||
3169 | <YueDisplay> | ||
3170 | <pre> | ||
3171 | segments = ["admin", "users", "logs", "view"] | ||
3172 | switch segments | ||
3173 | when [...groups, resource, action] | ||
3174 | print "Group:", groups -- ζε°: {"admin", "users"} | ||
3175 | print "Resource:", resource -- ζε°: "logs" | ||
3176 | print "Action:", action -- ζε°: "view" | ||
3177 | </pre> | ||
3178 | </YueDisplay> | ||
3179 | |||
2749 | ## ι’ε对豑ηΌη¨ | 3180 | ## ι’ε对豑ηΌη¨ |
2750 | 3181 | ||
2751 | ε¨δ»₯δΈηη€ΊδΎδΈοΌζδΉθζ¬ηζηLua代η ε―θ½ηθ΅·ζ₯δΌεΎε€ζγζδ»₯ζε₯½δΈ»θ¦ε ³ζ³¨ζδΉθζ¬δ»£η ε±ι’ηζδΉοΌηΆεε¦ζζ¨ζ³η₯ιε ³δΊι’ε对豑εθ½ηεη°η»θοΌεζ₯ηLua代η γ | 3182 | ε¨δ»₯δΈηη€ΊδΎδΈοΌζδΉθζ¬ηζηLua代η ε―θ½ηθ΅·ζ₯δΌεΎε€ζγζδ»₯ζε₯½δΈ»θ¦ε ³ζ³¨ζδΉθζ¬δ»£η ε±ι’ηζδΉοΌηΆεε¦ζδ½ ζ³η₯ιε ³δΊι’ε对豑εθ½ηεη°η»θοΌεζ₯ηLua代η γ |
2752 | 3183 | ||
2753 | δΈδΈͺηεηη±»οΌ | 3184 | δΈδΈͺηεηη±»οΌ |
2754 | 3185 | ||
@@ -3216,7 +3647,7 @@ x = class | |||
3216 | 3647 | ||
3217 | ### η±»ζ··ε | 3648 | ### η±»ζ··ε |
3218 | 3649 | ||
3219 | ζ¨ε―δ»₯ιθΏδ½Ώη¨ `using` ε ³ιεζ₯εη°η±»ζ··εγθΏζε³ηζ¨ε―δ»₯δ»δΈδΈͺζι Lua θ‘¨ζ Όζε·²εδΉη类对豑δΈοΌε€εΆε½ζ°ε°ζ¨εε»Ίηζ°η±»δΈγε½ζ¨δ½Ώη¨ζι Lua θ‘¨ζ ΌθΏθ‘η±»ζ··εζΆοΌζ¨ζζΊδΌη¨θͺε·±ηεη°ζ₯ιεη±»ηη΄’εΌζΉζ³οΌδΎε¦ε ζΉζ³ `__index`οΌγηΆθοΌε½ζ¨δ»δΈδΈͺ类对豑εζ··εζΆοΌιθ¦ζ³¨ζηζ―θ―₯类对豑ηε ζΉζ³ε°δΈδΌθ’«ε€εΆε°ζ°η±»γ | 3650 | δ½ ε―δ»₯ιθΏδ½Ώη¨ `using` ε ³ιεζ₯εη°η±»ζ··εγθΏζε³ηδ½ ε―δ»₯δ»δΈδΈͺζι Lua θ‘¨ζ Όζε·²εδΉη类对豑δΈοΌε€εΆε½ζ°ε°δ½ εε»Ίηζ°η±»δΈγε½δ½ δ½Ώη¨ζι Lua θ‘¨ζ ΌθΏθ‘η±»ζ··εζΆοΌδ½ ζζΊδΌη¨θͺε·±ηεη°ζ₯ιεη±»ηη΄’εΌζΉζ³οΌδΎε¦ε ζΉζ³ `__index`οΌγηΆθοΌε½δ½ δ»δΈδΈͺ类对豑εζ··εζΆοΌιθ¦ζ³¨ζηζ―θ―₯类对豑ηε ζΉζ³ε°δΈδΌθ’«ε€εΆε°ζ°η±»γ |
3220 | 3651 | ||
3221 | ```moonscript | 3652 | ```moonscript |
3222 | MyIndex = __index: var: 1 | 3653 | MyIndex = __index: var: 1 |
@@ -3318,22 +3749,22 @@ me = create_person "Leaf", [dad, mother, sister] | |||
3318 | 3749 | ||
3319 | ε¨ζ€η¨ζ³δΈοΌwithε―δ»₯θ’«θ§δΈΊKη»εεοΌk-combinatorοΌηδΈη§ηΉζε½’εΌγ | 3750 | ε¨ζ€η¨ζ³δΈοΌwithε―δ»₯θ’«θ§δΈΊKη»εεοΌk-combinatorοΌηδΈη§ηΉζε½’εΌγ |
3320 | 3751 | ||
3321 | ε¦ζζ¨ζ³η»θ‘¨θΎΎεΌε¦ε€θ΅·δΈδΈͺεη§°ηθ―οΌwithθ―ε₯δΈη葨达εΌδΉε―δ»₯ζ―δΈδΈͺθ΅εΌθ―ε₯γ | 3752 | ε¦ζδ½ ζ³η»θ‘¨θΎΎεΌε¦ε€θ΅·δΈδΈͺεη§°ηθ―οΌwithθ―ε₯δΈη葨达εΌδΉε―δ»₯ζ―δΈδΈͺθ΅εΌθ―ε₯γ |
3322 | 3753 | ||
3323 | ```moonscript | 3754 | ```moonscript |
3324 | with str = "δ½ ε₯½" | 3755 | with str := "δ½ ε₯½" |
3325 | print "εε§:", str | 3756 | print "εε§:", str |
3326 | print "ε€§ε:", \upper! | 3757 | print "ε€§ε:", \upper! |
3327 | ``` | 3758 | ``` |
3328 | <YueDisplay> | 3759 | <YueDisplay> |
3329 | <pre> | 3760 | <pre> |
3330 | with str = "δ½ ε₯½" | 3761 | with str := "δ½ ε₯½" |
3331 | print "εε§:", str | 3762 | print "εε§:", str |
3332 | print "ε€§ε:", \upper! | 3763 | print "ε€§ε:", \upper! |
3333 | </pre> | 3764 | </pre> |
3334 | </YueDisplay> | 3765 | </YueDisplay> |
3335 | 3766 | ||
3336 | ε¨withθ―ε₯δΈε―δ»₯δ½Ώη¨`[]`θΏιηΉζιγ | 3767 | δ½ ε―δ»₯ε¨ `with` θ―ε₯δΈδ½Ώη¨ `[]` θΏιηΉζιγ |
3337 | 3768 | ||
3338 | ```moonscript | 3769 | ```moonscript |
3339 | with tb | 3770 | with tb |
@@ -3356,6 +3787,19 @@ with tb | |||
3356 | </pre> | 3787 | </pre> |
3357 | </YueDisplay> | 3788 | </YueDisplay> |
3358 | 3789 | ||
3790 | `with?` ζ― `with` θ―ζ³ηδΈδΈͺε’εΌΊηζ¬οΌεΌε ₯δΊεε¨ζ§ζ£ζ₯οΌη¨δΊε¨δΈζΎεΌε€η©Ίηζ ε΅δΈεε ¨θΏιε―θ½δΈΊ nil η对豑γ | ||
3791 | |||
3792 | ```moonscript | ||
3793 | with? obj | ||
3794 | print obj.name | ||
3795 | ``` | ||
3796 | <YueDisplay> | ||
3797 | <pre> | ||
3798 | with? obj | ||
3799 | print obj.name | ||
3800 | </pre> | ||
3801 | </YueDisplay> | ||
3802 | |||
3359 | ## do θ―ε₯ | 3803 | ## do θ―ε₯ |
3360 | 3804 | ||
3361 | ε½η¨δ½θ―ε₯ζΆοΌdoθ―ε₯ηδ½η¨ε°±εε¨LuaδΈε·δΈε€γ | 3805 | ε½η¨δ½θ―ε₯ζΆοΌdoθ―ε₯ηδ½η¨ε°±εε¨LuaδΈε·δΈε€γ |
@@ -3375,7 +3819,7 @@ print var -- θΏιζ―nil | |||
3375 | </pre> | 3819 | </pre> |
3376 | </YueDisplay> | 3820 | </YueDisplay> |
3377 | 3821 | ||
3378 | ζδΉθζ¬η **do** δΉε―δ»₯η¨δ½θ‘¨θΎΎεΌγε θΈζ¨ε°ε€θ‘代η ηε€ηεεΉΆδΈΊδΈδΈͺ葨达εΌοΌεΉΆε°doθ―ε₯代η εηζεδΈδΈͺθ―ε₯δ½δΈΊθ‘¨θΎΎεΌθΏεηη»ζγ | 3822 | ζδΉθζ¬η **do** δΉε―δ»₯η¨δ½θ‘¨θΎΎεΌγε θΈδ½ ε°ε€θ‘代η ηε€ηεεΉΆδΈΊδΈδΈͺ葨达εΌοΌεΉΆε°doθ―ε₯代η εηζεδΈδΈͺθ―ε₯δ½δΈΊθ‘¨θΎΎεΌθΏεηη»ζγ |
3379 | 3823 | ||
3380 | ```moonscript | 3824 | ```moonscript |
3381 | counter = do | 3825 | counter = do |
@@ -4334,8 +4778,8 @@ simplified: boolean | |||
4334 | 4778 | ||
4335 | ηζ (c) 2017-2025 ζηΎ \<dragon-fly@qq.com\> | 4779 | ηζ (c) 2017-2025 ζηΎ \<dragon-fly@qq.com\> |
4336 | 4780 | ||
4337 | ηΉζ€ε θ΄ΉζδΊδ»»δ½θ·εΎζ¬θ½―δ»Άε―ζ¬εηΈε ³ζζ‘£ζδ»ΆοΌδΈη§°βθ½―δ»ΆβοΌηδΊΊδΈειεΆε°ε€η½θ―₯θ½―δ»Άηζε©οΌε ζ¬δΈειεΆε°δ½Ώη¨γε€εΆγδΏζΉγεεΉΆγεεΈγεεγ转ζθΈε―ε/ζεΊεθ―₯θ½―δ»Άε―ζ¬οΌδ»₯εεζζθ’«ι εδΊζ¬θ½―δ»ΆηδΊΊε¦δΈηζε©οΌι‘»ε¨δΈεζ‘δ»ΆδΈοΌ | 4781 | ηΉζ€ε θ΄ΉζδΊδ»»δ½θ·εΎζ¬θ½―δ»Άε―ζ¬εηΈε ³ζζ‘£ζδ»ΆοΌδΈη§°βθ½―δ»ΆβοΌηδΊΊδΈειεΆε°ε€η½θ―₯θ½―δ»Άηζε©οΌε ζ¬δΈειεΆε°δ½Ώη¨γε€εΆγδΏζΉγεεΉΆγεεΈγεεγ转ζθΈε―ε/ζεΊεθ―₯θ½―δ»Άε―ζ¬οΌδ»₯εεζζθ’«ι εδΊζ¬θ½―δ»ΆηδΊΊε¦δΈηζε©οΌι‘»ε¨δΈεζ‘δ»ΆδΈοΌ |
4338 | δΈθΏ°ηζε£°ζεζ¬θΈε―ε£°ζεΊε ε«ε¨θ―₯θ½―δ»Άηζζε―ζ¬ζε质ζεδΈγ | 4782 | δΈθΏ°ηζε£°ζεζ¬θΈε―ε£°ζεΊε ε«ε¨θ―₯θ½―δ»Άηζζε―ζ¬ζε质ζεδΈγ |
4339 | ζ¬θ½―δ»Άζ―βε¦ζ€βζδΎηοΌζ²‘ζδ»»δ½ε½’εΌηζη€Ίζζη€ΊηδΏθ―οΌε ζ¬δ½δΈιδΊε―Ήιιζ§γηΉεη¨ιηιη¨ζ§εδΈδΎ΅ζηδΏθ―γε¨δ»»δ½ζ ε΅δΈοΌδ½θ ζηζζζδΊΊι½δΈε―Ήδ»»δ½η΄’θ΅γζε³ζε Άδ»θ΄£δ»»θ΄θ΄£οΌζ θΊθΏδΊθΏ½θ΄£ζ₯θͺεεγδΎ΅ζζε Άεθ‘δΈΊδΈοΌθΏζ―δΊ§ηδΊγζΊδΊζζε ³δΊζ¬θ½―δ»Άδ»₯εζ¬θ½―δ»Άηδ½Ώη¨ζε Άεε€η½γ | 4783 | ζ¬θ½―δ»Άζ―βε¦ζ€βζδΎηοΌζ²‘ζδ»»δ½ε½’εΌηζη€Ίζζη€ΊηδΏθ―οΌε ζ¬δ½δΈιδΊε―Ήιιζ§γηΉεη¨ιηιη¨ζ§εδΈδΎ΅ζηδΏθ―γε¨δ»»δ½ζ ε΅δΈοΌδ½θ ζηζζζδΊΊι½δΈε―Ήδ»»δ½η΄’θ΅γζε³ζε Άδ»θ΄£δ»»θ΄θ΄£οΌζ θΊθΏδΊθΏ½θ΄£ζ₯θͺεεγδΎ΅ζζε Άεθ‘δΈΊδΈοΌθΏζ―δΊ§ηδΊγζΊδΊζζε ³δΊζ¬θ½―δ»Άδ»₯εζ¬θ½―δ»Άηδ½Ώη¨ζε Άεε€η½γ |
4340 | 4784 | ||
4341 | <CompilerModal /> | 4785 | <CompilerModal /> |
diff --git a/spec/inputs/backcall.yue b/spec/inputs/backcall.yue index 8aadc71..e6b8c21 100644 --- a/spec/inputs/backcall.yue +++ b/spec/inputs/backcall.yue | |||
@@ -13,9 +13,9 @@ do | |||
13 | x > 2 | 13 | x > 2 |
14 | 14 | ||
15 | do | 15 | do |
16 | (data) <- http?.get "ajaxtest" | 16 | data <- http?.get "ajaxtest" |
17 | body[".result"]\html data | 17 | body[".result"]\html data |
18 | (processed) <- http.post "ajaxprocess", data | 18 | processed <- http.post "ajaxprocess", data |
19 | body[".result"]\append processed | 19 | body[".result"]\append processed |
20 | <- setTimeout 1000 | 20 | <- setTimeout 1000 |
21 | print "done" | 21 | print "done" |
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 674dfe4..b6250d0 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue | |||
@@ -94,7 +94,7 @@ do | |||
94 | -- | 94 | -- |
95 | 95 | ||
96 | do | 96 | do |
97 | with {a,b} = thing | 97 | with {a,b} := thing |
98 | print a, b | 98 | print a, b |
99 | 99 | ||
100 | 100 | ||
@@ -240,5 +240,43 @@ do | |||
240 | switch tb | 240 | switch tb |
241 | when {c: {<"abc">: meta_field = "def"}, <[[any string]]>: {d: abc = 123}, <'str'>: {e: def = {}}} | 241 | when {c: {<"abc">: meta_field = "def"}, <[[any string]]>: {d: abc = 123}, <'str'>: {e: def = {}}} |
242 | print meta_field, abc, def | 242 | print meta_field, abc, def |
243 | |||
244 | do | ||
245 | clients = ["VIP_Alice", "User_Bob", "User_Clara", "VIP_Eva"] | ||
246 | [vipStart, ...regulars, vipEnd] = clients | ||
247 | print vipStart -- "VIP_Alice" | ||
248 | print regulars -- {"User_Bob", "User_Clara"} | ||
249 | print vipEnd -- "VIP_Eva" | ||
250 | |||
251 | do | ||
252 | setupMeeting = (participants) -> | ||
253 | [chair, ..._, secretary] = participants | ||
254 | print chair, secretary | ||
255 | |||
256 | setupMeeting ["Alice", "Bob", "Charlie", "David"] | ||
257 | -- Output: Alice David | ||
258 | |||
259 | do | ||
260 | getTransactions = -> | ||
261 | { | ||
262 | {id: "T1", amount: 100} | ||
263 | {id: "T2", amount: 200} | ||
264 | {id: "T3", amount: 300} | ||
265 | } | ||
266 | |||
267 | :id, :amount = getTransactions![#] | ||
268 | assert id == "T3" | ||
269 | assert amount == 300 | ||
270 | |||
271 | do | ||
272 | [ | ||
273 | _ | ||
274 | ...middle | ||
275 | _ | ||
276 | ] = tb | ||
277 | |||
278 | do | ||
279 | {a, :abc, b, :def, ...sub, d, e} = tb | ||
280 | |||
243 | nil | 281 | nil |
244 | 282 | ||
diff --git a/spec/inputs/global.yue b/spec/inputs/global.yue index ce1cc15..4e3b8aa 100644 --- a/spec/inputs/global.yue +++ b/spec/inputs/global.yue | |||
@@ -82,3 +82,9 @@ do | |||
82 | FooBar = "pascal case" | 82 | FooBar = "pascal case" |
83 | FOOBAR = "all uppercase" | 83 | FOOBAR = "all uppercase" |
84 | 84 | ||
85 | do | ||
86 | global const class A | ||
87 | global const Flag = 1 | ||
88 | global const const, x, y = "const", 1, 2 | ||
89 | global const math, table | ||
90 | |||
diff --git a/spec/inputs/import.yue b/spec/inputs/import.yue index b8ffc24..8982e6c 100644 --- a/spec/inputs/import.yue +++ b/spec/inputs/import.yue | |||
@@ -139,3 +139,13 @@ do | |||
139 | import "m" as {c: d} | 139 | import "m" as {c: d} |
140 | import "m" as {g, {<close>: i}} | 140 | import "m" as {g, {<close>: i}} |
141 | 141 | ||
142 | do | ||
143 | import require | ||
144 | import string as stringlib | ||
145 | import string.format | ||
146 | import io.read as io_read | ||
147 | |||
148 | type = -> | ||
149 | import type as tp | ||
150 | import ζ as yue | ||
151 | |||
diff --git a/spec/inputs/lists.yue b/spec/inputs/lists.yue index 921cae0..c493b68 100644 --- a/spec/inputs/lists.yue +++ b/spec/inputs/lists.yue | |||
@@ -87,4 +87,51 @@ do | |||
87 | [a, b] = hello | 87 | [a, b] = hello |
88 | [name = "nameless", job = "jobless"] = person | 88 | [name = "nameless", job = "jobless"] = person |
89 | 89 | ||
90 | do | ||
91 | transactions = ["T001", "T002", "T003", "T004", "T005"] | ||
92 | middleTransactions = transactions[2, -2] | ||
93 | print middleTransactions -- => {"T002", "T003", "T004"} | ||
94 | |||
95 | do | ||
96 | logs = | ||
97 | - start: 0, end: 100 | ||
98 | - start: 100, end: 200 | ||
99 | - start: 200, end: 123 | ||
100 | print logs[#].end -- => 123 | ||
101 | |||
102 | do | ||
103 | pendingOrders = ["O001", "O002", "O003", "O004"] | ||
104 | print pendingOrders[# - 1] -- => "O003" | ||
105 | |||
106 | do | ||
107 | getOrders = -> | ||
108 | { | ||
109 | { id: "O1001", status: "pending" } | ||
110 | { id: "O1002", status: "processing" } | ||
111 | { id: "O1003", status: "done" } | ||
112 | } | ||
113 | |||
114 | lastStatus = getOrders()[#].status | ||
115 | assert lastStatus == "done" | ||
116 | |||
117 | do | ||
118 | cloneList1 = (list) -> list[,] | ||
119 | cloneList2 = (list) -> [...list,] | ||
120 | cloneTable = (tb) -> {...tb} | ||
121 | |||
122 | do | ||
123 | print( | ||
124 | globalTB[#] | ||
125 | a.b.c[# - 2] | ||
126 | x?\y?!.z?[# - 3] | ||
127 | ) | ||
128 | |||
129 | do | ||
130 | f = -> | ||
131 | print( | ||
132 | globalTB[#]\end 123 | ||
133 | a.b.c[5,-5][# - 2] | ||
134 | x?\y?!.z?[# - 3]?[, -3] | ||
135 | ) | ||
136 | |||
90 | nil | 137 | nil |
diff --git a/spec/inputs/literals.yue b/spec/inputs/literals.yue index 6b666f0..32cf7e7 100644 --- a/spec/inputs/literals.yue +++ b/spec/inputs/literals.yue | |||
@@ -10,10 +10,19 @@ _ = { | |||
10 | 0xfF2323 | 10 | 0xfF2323 |
11 | 0xabcdef | 11 | 0xabcdef |
12 | 0xABCDEF | 12 | 0xABCDEF |
13 | 0XFB_C4_00 | ||
13 | 0x123p-123 | 14 | 0x123p-123 |
14 | 0xABCP+321 | 15 | 0xABCP+321 |
15 | 0x.1p-111 | 16 | 0x.1p-111 |
16 | 0xA_B_CP-3_2_1 | 17 | 0xA_B_CP-3_2_1 |
18 | 0x0.1E | ||
19 | 0xA23p-4 | ||
20 | 0X1.921FB54442D18P+1 | ||
21 | |||
22 | 0b01 | ||
23 | 0b00_00_10_00 | ||
24 | 0B1111 | ||
25 | 0B00_11_00_10_01 | ||
17 | 26 | ||
18 | .2323 | 27 | .2323 |
19 | .2323e-1 | 28 | .2323e-1 |
diff --git a/spec/inputs/loops.yue b/spec/inputs/loops.yue index c5b28b3..5df10ca 100644 --- a/spec/inputs/loops.yue +++ b/spec/inputs/loops.yue | |||
@@ -213,3 +213,55 @@ do | |||
213 | do | 213 | do |
214 | until x := func 'a', b do | 214 | until x := func 'a', b do |
215 | print "false expected" | 215 | print "false expected" |
216 | |||
217 | do | ||
218 | index = for i = 1, #tb | ||
219 | break i if tb[i] | ||
220 | |||
221 | f for i = 1, #tb | ||
222 | break i if tb[i] | ||
223 | |||
224 | f for i = 1, #tb | ||
225 | i if tb[i] | ||
226 | |||
227 | i = 1 | ||
228 | ids = while tb[i] | ||
229 | i += 1 | ||
230 | i - 1 | ||
231 | |||
232 | i = 1 | ||
233 | idx = while tb[i] | ||
234 | i += 1 | ||
235 | break i - 1 | ||
236 | |||
237 | f1 = -> | ||
238 | i = 1 | ||
239 | f while tb[i] | ||
240 | i += 1 | ||
241 | i - 1 | ||
242 | |||
243 | i = 1 | ||
244 | f while tb[i] | ||
245 | i += 1 | ||
246 | break i - 1 | ||
247 | |||
248 | list = for item in *items | ||
249 | switch item | ||
250 | when type: "A", :value | ||
251 | if value > 5 | ||
252 | item | ||
253 | |||
254 | do | ||
255 | repeat print 1 until true | ||
256 | |||
257 | x = repeat | ||
258 | a = func! | ||
259 | break a.x | ||
260 | until a.v | ||
261 | |||
262 | items = repeat | ||
263 | item = getItem! | ||
264 | break unless item | ||
265 | item if item.value > 0 | ||
266 | until false | ||
267 | |||
diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue index 5d5f1a9..191f09f 100644 --- a/spec/inputs/macro.yue +++ b/spec/inputs/macro.yue | |||
@@ -60,6 +60,11 @@ macro NumAndStr = (num, str) -> | |||
60 | 60 | ||
61 | print $NumAndStr 123, 'xyz' | 61 | print $NumAndStr 123, 'xyz' |
62 | 62 | ||
63 | macro NumAndStr2 = (num`Num, str`SingleString) -> | | ||
64 | [#{num}, #{str}] | ||
65 | |||
66 | print $NumAndStr2 456, 'abc' | ||
67 | |||
63 | $asserts item == nil | 68 | $asserts item == nil |
64 | 69 | ||
65 | $myconfig false | 70 | $myconfig false |
@@ -100,13 +105,14 @@ macro filter = (items, action)-> | |||
100 | $showMacro "filter", "[_ for _ in *#{items} when #{action}]" | 105 | $showMacro "filter", "[_ for _ in *#{items} when #{action}]" |
101 | 106 | ||
102 | macro reduce = (items, def, action)-> | 107 | macro reduce = (items, def, action)-> |
103 | $showMacro "reduce", "if ##{items} == 0 | 108 | $showMacro "reduce", | |
104 | #{def} | 109 | if ##{items} == 0 |
105 | else | 110 | #{def} |
106 | _1 = #{def} | 111 | else |
107 | for _2 in *#{items} | 112 | _1 = #{def} |
108 | _1 = #{action} | 113 | for _2 in *#{items} |
109 | _1" | 114 | _1 = #{action} |
115 | _1 | ||
110 | 116 | ||
111 | macro foreach = (items, action)-> | 117 | macro foreach = (items, action)-> |
112 | $showMacro "foreach", "for _ in *#{items} | 118 | $showMacro "foreach", "for _ in *#{items} |
@@ -154,13 +160,15 @@ macro curry = (...)-> | |||
154 | f = $curry x,y,z,do | 160 | f = $curry x,y,z,do |
155 | print x,y,z | 161 | print x,y,z |
156 | 162 | ||
157 | macro get_inner = (var)-> "do | 163 | macro get_inner = (var)-> | |
158 | a = 1 | 164 | do |
159 | a + 1" | 165 | a = 1 |
166 | a + 1 | ||
160 | 167 | ||
161 | macro get_inner_hygienic = (var)-> "(-> | 168 | macro get_inner_hygienic = (var)-> | |
162 | local a = 1 | 169 | (-> |
163 | a + 1)!" | 170 | local a = 1 |
171 | a + 1)! | ||
164 | 172 | ||
165 | do | 173 | do |
166 | a = 8 | 174 | a = 8 |
@@ -196,6 +204,18 @@ end | |||
196 | 204 | ||
197 | print x | 205 | print x |
198 | 206 | ||
207 | import "yue" | ||
208 | macro lua = (code`YAMLMultiline) -> { | ||
209 | code: yue.loadstring(code)! | ||
210 | type: "lua" | ||
211 | } | ||
212 | |||
213 | $lua | | ||
214 | local function f2(a) | ||
215 | return a + 1 | ||
216 | end | ||
217 | x = x + f2(3) | ||
218 | |||
199 | macro def = (fname, ...)-> | 219 | macro def = (fname, ...)-> |
200 | args = {...} | 220 | args = {...} |
201 | last = table.remove args | 221 | last = table.remove args |
@@ -317,7 +337,13 @@ $chainC( | |||
317 | Destroy! | 337 | Destroy! |
318 | ) | 338 | ) |
319 | 339 | ||
320 | macro tb = -> "{'abc', a:123, <call>:=> 998}" | 340 | macro tb = -> | |
341 | { | ||
342 | 'abc' | ||
343 | a: 123 | ||
344 | <call>: => 998 | ||
345 | } | ||
346 | |||
321 | print $tb[1], $tb.a, ($tb)!, $tb! | 347 | print $tb[1], $tb.a, ($tb)!, $tb! |
322 | 348 | ||
323 | print "current line: #{ $LINE }" | 349 | print "current line: #{ $LINE }" |
diff --git a/spec/inputs/macro_export.yue b/spec/inputs/macro_export.yue index cc7d459..22905b5 100644 --- a/spec/inputs/macro_export.yue +++ b/spec/inputs/macro_export.yue | |||
@@ -8,13 +8,12 @@ export macro config = (debugging = true)-> | |||
8 | "" | 8 | "" |
9 | 9 | ||
10 | export macro showMacro = (name, res)-> | 10 | export macro showMacro = (name, res)-> |
11 | if debugMacro then " | 11 | if debugMacro then | |
12 | do | 12 | do |
13 | txt = #{res} | 13 | txt = #{res} |
14 | print '[macro ' .. #{name} .. ']' | 14 | print '[macro #{name}]' |
15 | print txt | 15 | print txt |
16 | txt | 16 | txt |
17 | " | ||
18 | else | 17 | else |
19 | res | 18 | res |
20 | 19 | ||
@@ -35,14 +34,16 @@ export macro copy = (src, dst, ...)-> | |||
35 | src != "_src_" and src != "_dst_" and dst != "_src_" and dst != "_dst_" | 34 | src != "_src_" and src != "_dst_" and dst != "_src_" and dst != "_dst_" |
36 | "copy targets can not be _src_ or _dst_" | 35 | "copy targets can not be _src_ or _dst_" |
37 | ) | 36 | ) |
38 | " | 37 | copyFields = table.concat( |
39 | do | 38 | ["_dst_.#{field} = _src_.#{field}" for field in *{...}] |
40 | local _src_, _dst_ | 39 | "\n\t\t\t" |
41 | with _dst_ = #{dst} | 40 | ) |
42 | with _src_ = #{src} | 41 | | |
43 | #{table.concat for field in *{...} do " | 42 | do |
44 | _dst_.#{field} = _src_.#{field} | 43 | local _src_, _dst_ |
45 | "}" | 44 | with _dst_ := #{dst} |
45 | with _src_ := #{src} | ||
46 | #{copyFields} | ||
46 | 47 | ||
47 | export macro enum = (...) -> | 48 | export macro enum = (...) -> |
48 | items = {...} | 49 | items = {...} |
diff --git a/spec/inputs/macro_teal.yue b/spec/inputs/macro_teal.yue index 0cfd862..e51bcd7 100644 --- a/spec/inputs/macro_teal.yue +++ b/spec/inputs/macro_teal.yue | |||
@@ -4,11 +4,16 @@ $ -> | |||
4 | options.target_extension = "tl" | 4 | options.target_extension = "tl" |
5 | package.path ..= ";./spec/lib/?.lua" | 5 | package.path ..= ";./spec/lib/?.lua" |
6 | 6 | ||
7 | macro to_lua = (code)-> | 7 | macro to_lua = (code)-> | |
8 | "require('yue').to_lua(#{code}, reserve_line_number:false, same_module:true)" | 8 | require('yue').to_lua #{code}, |
9 | reserve_line_number: false | ||
10 | same_module: true | ||
9 | 11 | ||
10 | macro trim = (name)-> | 12 | macro trim = (name)-> | |
11 | "if result := #{name}\\match '[\\'\"](.*)[\\'\"]' then result else #{name}" | 13 | if result := #{name}\match '[\'"](.*)[\'"]' |
14 | result | ||
15 | else | ||
16 | #{name} | ||
12 | 17 | ||
13 | export macro local = (decl, value = nil)-> | 18 | export macro local = (decl, value = nil)-> |
14 | import "yue" as {options:{:tl_enabled}} | 19 | import "yue" as {options:{:tl_enabled}} |
diff --git a/spec/inputs/macro_todo.yue b/spec/inputs/macro_todo.yue index 752c9cb..c9c8f77 100644 --- a/spec/inputs/macro_todo.yue +++ b/spec/inputs/macro_todo.yue | |||
@@ -5,9 +5,6 @@ export macro todoInner = (module, line, msg)-> | |||
5 | type: "lua" | 5 | type: "lua" |
6 | } | 6 | } |
7 | 7 | ||
8 | export macro todo = (msg)-> | 8 | export macro todo = (msg)-> | |
9 | if msg | 9 | $todoInner $FILE, $LINE#{msg and ", #{msg}" or ""} |
10 | "$todoInner $FILE, $LINE, #{msg}" | ||
11 | else | ||
12 | "$todoInner $FILE, $LINE" | ||
13 | 10 | ||
diff --git a/spec/inputs/props.yue b/spec/inputs/props.yue new file mode 100644 index 0000000..bbb7aae --- /dev/null +++ b/spec/inputs/props.yue | |||
@@ -0,0 +1,61 @@ | |||
1 | class Props | ||
2 | __index: (name): nil => | ||
3 | cls = @.<> | ||
4 | if item := cls.__getter?[name] -- access properties | ||
5 | return item @ | ||
6 | elseif item := rawget cls, name -- access member functions | ||
7 | return item | ||
8 | else | ||
9 | c = cls | ||
10 | while c := c.<> -- recursive to access base classes | ||
11 | if item := c.__getter?[name] | ||
12 | cls.__getter ??= {} | ||
13 | cls.__getter[name] = item -- cache base properties to class | ||
14 | return item @ | ||
15 | elseif item := rawget c, name | ||
16 | rawset cls, name, item -- cache base member to class | ||
17 | return item | ||
18 | |||
19 | __newindex: (name, value) => | ||
20 | cls = @.<> | ||
21 | if item := cls.__setter?[name] -- access properties | ||
22 | item @, value | ||
23 | else | ||
24 | c = cls | ||
25 | while c := c.<> -- recursive to access base classes | ||
26 | if item := c.__setter?[name] | ||
27 | cls.__setter ??= {} | ||
28 | cls.__setter[name] = item -- cache base property to class | ||
29 | item @, value | ||
30 | return | ||
31 | rawset @, name, value -- assign field to self | ||
32 | |||
33 | assignReadOnly = -> error "assigning a readonly property" | ||
34 | |||
35 | prop: (name, props) => | ||
36 | { | ||
37 | :get | ||
38 | :set = assignReadOnly | ||
39 | } = props | ||
40 | if getter := rawget @__base, "__getter" | ||
41 | getter[name] = get | ||
42 | else | ||
43 | rawset @__base, "__getter", [name]: get | ||
44 | if setter := rawget @__base, "__setter" | ||
45 | setter[name] = set | ||
46 | else | ||
47 | rawset @__base, "__setter", [name]: set | ||
48 | |||
49 | class A extends Props | ||
50 | @prop 'x' | ||
51 | get: => @_x + 1000 | ||
52 | set: (v) => @_x = v | ||
53 | new: => | ||
54 | @_x = 0 | ||
55 | |||
56 | class B extends A | ||
57 | @prop 'abc', get: => "hello" | ||
58 | |||
59 | b = B! | ||
60 | b.x = 999 | ||
61 | print b.x, b.abc | ||
diff --git a/spec/inputs/string.yue b/spec/inputs/string.yue index f91383e..1f0fba8 100644 --- a/spec/inputs/string.yue +++ b/spec/inputs/string.yue | |||
@@ -74,3 +74,76 @@ _ = "hello" | |||
74 | something"hello"\world! | 74 | something"hello"\world! |
75 | something "hello"\world! | 75 | something "hello"\world! |
76 | 76 | ||
77 | do | ||
78 | str = | | ||
79 | key: value | ||
80 | str = | | ||
81 | config: | ||
82 | enabled: true | ||
83 | level: 5 | ||
84 | str = | | ||
85 | header: start | ||
86 | |||
87 | footer: end | ||
88 | str = | | ||
89 | name: #{username} | ||
90 | str = | | ||
91 | count: #{total} items | ||
92 | str = | | ||
93 | user: #{name} | ||
94 | id: #{id} | ||
95 | str = | | ||
96 | path: "C:\\Program Files\\App" | ||
97 | desc: 'single "quote" test' | ||
98 | str = | | ||
99 | key: value | ||
100 | next: 123 | ||
101 | str = | | ||
102 | list: | ||
103 | - "one" | ||
104 | - "two" | ||
105 | str = | | ||
106 | -- comment | ||
107 | content text | ||
108 | -- comment | ||
109 | str = | | ||
110 | #{1 + 2} | ||
111 | #{2 + 3} | ||
112 | #{"a" .. "b"} | ||
113 | obj = | ||
114 | settings: | | ||
115 | mode: #{mode} | ||
116 | flags: | ||
117 | - #{flag1} | ||
118 | - default | ||
119 | fn = -> | | ||
120 | Hello | ||
121 | name: #{userName} | ||
122 | str = | | ||
123 | result: | ||
124 | status: #{if ok then "pass" else "fail"} | ||
125 | code: #{code} | ||
126 | summary = | | ||
127 | date: #{os.date()} | ||
128 | values: | ||
129 | - | ||
130 | a: #{aVal} | ||
131 | b: #{bVal or defaultB} | ||
132 | msg = send | | ||
133 | Hello, #{user}! | ||
134 | Today is #{os.date("%A")}. | ||
135 | desc = do | ||
136 | prefix = "Result" | ||
137 | | | ||
138 | #{prefix}: | ||
139 | value: #{compute!} | ||
140 | (| | ||
141 | 1 | ||
142 | 2 | ||
143 | 3 | ||
144 | |||
145 | |||
146 | export yaml = | | ||
147 | version: #{ver} | ||
148 | ok: true | ||
149 | |||
diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue index 49d47f3..2b0669c 100644 --- a/spec/inputs/switch.yue +++ b/spec/inputs/switch.yue | |||
@@ -165,5 +165,128 @@ do | |||
165 | print item | 165 | print item |
166 | when [a = 1, b = "abc"] | 166 | when [a = 1, b = "abc"] |
167 | print a, b | 167 | print a, b |
168 | nil | ||
169 | 168 | ||
169 | do | ||
170 | switch tb | ||
171 | when [1, 2, 3] | ||
172 | print "1, 2, 3" | ||
173 | when [1, b, 3] | ||
174 | print "1, #{b}, 3" | ||
175 | when [1, 2, b = 3] | ||
176 | print "1, 2, #{b}" | ||
177 | |||
178 | do | ||
179 | switch tb | ||
180 | when success: true, :result | ||
181 | print "success", result | ||
182 | when success: false | ||
183 | print "failed", result | ||
184 | else | ||
185 | print "invalid" | ||
186 | |||
187 | do | ||
188 | switch tb | ||
189 | when {type: "success", :content} | ||
190 | print "success", content | ||
191 | when {type: "error", :content} | ||
192 | print "failed", content | ||
193 | else | ||
194 | print "invalid" | ||
195 | |||
196 | do | ||
197 | switch tb | ||
198 | when [ | ||
199 | {a: 1, b: 2} | ||
200 | {a: 3, b: 4} | ||
201 | {a: 5, b: 6} | ||
202 | fourth | ||
203 | ] | ||
204 | print "matched", fourth | ||
205 | |||
206 | switch tb | ||
207 | when [ | ||
208 | {c: 1, d: 2} | ||
209 | {c: 3, d: 4} | ||
210 | {c: 5, d: 6} | ||
211 | ] | ||
212 | print "OK" | ||
213 | when [ | ||
214 | _ | ||
215 | _ | ||
216 | {a: 1, b: 2} | ||
217 | {a: 3, b: 4} | ||
218 | {a: 5, b: 6} | ||
219 | sixth | ||
220 | ] | ||
221 | print "matched", sixth | ||
222 | |||
223 | do | ||
224 | switch v := "hello" | ||
225 | when "hello" | ||
226 | print "matched hello" | ||
227 | else | ||
228 | print "not matched" | ||
229 | -- output: matched hello | ||
230 | |||
231 | do | ||
232 | f = -> "ok" | ||
233 | switch val := f! | ||
234 | when "ok" | ||
235 | print "it's ok" | ||
236 | -- output: it's ok | ||
237 | |||
238 | |||
239 | do | ||
240 | g = -> 42 | ||
241 | switch result := g! | ||
242 | when 1, 2 | ||
243 | print "small" | ||
244 | when 42 | ||
245 | print "life universe everything" | ||
246 | else | ||
247 | print "other #{result}" | ||
248 | -- output: life universe everything | ||
249 | |||
250 | do | ||
251 | check = -> | ||
252 | if true | ||
253 | "yes" | ||
254 | else | ||
255 | "no" | ||
256 | |||
257 | switch x := check! | ||
258 | when "yes" | ||
259 | print "affirmative" | ||
260 | else | ||
261 | print "negative" | ||
262 | -- output: affirmative | ||
263 | |||
264 | do | ||
265 | t = (): tb -> | ||
266 | tb = {a: 1} | ||
267 | tb.a = 2 | ||
268 | |||
269 | switch data := t! | ||
270 | when {a: 2} | ||
271 | print "matched" | ||
272 | else | ||
273 | print "not matched" | ||
274 | |||
275 | do | ||
276 | clientData = ["Meta", "CUST_1001", "CHK123"] | ||
277 | switch clientData | ||
278 | when [...metadata, customerId, checksum] | ||
279 | print metadata -- {"Meta"} | ||
280 | print customerId -- "CUST_1001" | ||
281 | print checksum -- "CHK123" | ||
282 | |||
283 | do | ||
284 | handlePath = (segments) -> | ||
285 | switch segments | ||
286 | when [..._, resource, action] | ||
287 | print "Resource:", resource | ||
288 | print "Action:", action | ||
289 | |||
290 | handlePath ["admin", "logs", "view"] | ||
291 | |||
292 | nil | ||
diff --git a/spec/inputs/tables.yue b/spec/inputs/tables.yue index 0de8a8c..702e04a 100644 --- a/spec/inputs/tables.yue +++ b/spec/inputs/tables.yue | |||
@@ -245,6 +245,24 @@ menus = | |||
245 | click: -> | 245 | click: -> |
246 | } | 246 | } |
247 | 247 | ||
248 | _ = | ||
249 | boolean: | ||
250 | - true | ||
251 | - false | ||
252 | float: | ||
253 | - 3.14 | ||
254 | - -6.8523015e+5 | ||
255 | int: | ||
256 | - 123 | ||
257 | - -0b1010_0111_0100_1010_1110 | ||
258 | null: | ||
259 | nodeName: 'node' | ||
260 | parent: nil | ||
261 | string: | ||
262 | - 'Hello world' | ||
263 | - "newline | ||
264 | newline2" | ||
265 | |||
248 | tb = {...other} | 266 | tb = {...other} |
249 | 267 | ||
250 | tbMix = { | 268 | tbMix = { |
diff --git a/spec/inputs/try_catch.yue b/spec/inputs/try_catch.yue index 4e05bc6..6c29a52 100644 --- a/spec/inputs/try_catch.yue +++ b/spec/inputs/try_catch.yue | |||
@@ -62,6 +62,126 @@ f = -> | |||
62 | do | 62 | do |
63 | <- x | 63 | <- x |
64 | local tb, a, b, c | 64 | local tb, a, b, c |
65 | f = -> try tb.f a, b, c | 65 | f1 = -> try tb.f a, b, c |
66 | |||
67 | do | ||
68 | f1 = -> do | ||
69 | ok, ... = try func! | ||
70 | ... | ||
71 | |||
72 | do | ||
73 | local func | ||
74 | a, b, c = try? func! | ||
75 | |||
76 | do | ||
77 | a, b, c = try? func! | ||
78 | |||
79 | do | ||
80 | a = (try? func!) ?? "default" | ||
81 | |||
82 | do | ||
83 | f try? func! | ||
84 | |||
85 | do | ||
86 | f try? | ||
87 | print 123 | ||
88 | func! | ||
89 | catch e | ||
90 | print e | ||
91 | e | ||
66 | 92 | ||
67 | nil | 93 | nil |
94 | |||
95 | do | ||
96 | try | ||
97 | func 1, 2, 3 | ||
98 | catch err | ||
99 | print err | ||
100 | |||
101 | try func 1, 2, 3 | ||
102 | catch err | ||
103 | print err | ||
104 | |||
105 | try | ||
106 | print "trying" | ||
107 | func 1, 2, 3 | ||
108 | |||
109 | do | ||
110 | success, result = try | ||
111 | func 1, 2, 3 | ||
112 | catch err | ||
113 | print err | ||
114 | |||
115 | success, result = try func 1, 2, 3 | ||
116 | |||
117 | tb = {} | ||
118 | |||
119 | try tb.func | ||
120 | try tb.func! | ||
121 | try tb.func() | ||
122 | try (tb.func!) | ||
123 | try (tb\func(1, 2, 3)) | ||
124 | |||
125 | try tb.func 1 | ||
126 | try tb.func(1) | ||
127 | |||
128 | if (try func 1 | ||
129 | catch err | ||
130 | print err) | ||
131 | print "OK" | ||
132 | |||
133 | if try (func 1) | ||
134 | catch err | ||
135 | print err | ||
136 | print "OK" | ||
137 | |||
138 | do | ||
139 | if success, result := try func "abc", 123 | ||
140 | print result | ||
141 | |||
142 | success, result = try func "abc", 123 | ||
143 | catch err | ||
144 | print err | ||
145 | |||
146 | print result if success, result := try func "abc", 123 | ||
147 | catch err | ||
148 | print err | ||
149 | |||
150 | do | ||
151 | try | ||
152 | func 1, 2, 3 | ||
153 | |||
154 | try func 1, 2, 3 | ||
155 | |||
156 | do | ||
157 | <- x | ||
158 | local tb, a, b, c | ||
159 | f1 = -> try tb.f a, b, c | ||
160 | |||
161 | do | ||
162 | f1 = -> do | ||
163 | ok, ... = try func! | ||
164 | ... | ||
165 | |||
166 | do | ||
167 | local func | ||
168 | a, b, c = try? func! | ||
169 | |||
170 | do | ||
171 | a, b, c = try? func! | ||
172 | |||
173 | do | ||
174 | a = (try? func!) ?? "default" | ||
175 | |||
176 | do | ||
177 | f try? func! | ||
178 | |||
179 | do | ||
180 | f try? | ||
181 | print 123 | ||
182 | func! | ||
183 | catch e | ||
184 | print e | ||
185 | e | ||
186 | |||
187 | nil | ||
diff --git a/spec/inputs/unicode/destructure.yue b/spec/inputs/unicode/destructure.yue index 3c3a369..a5ffd5d 100644 --- a/spec/inputs/unicode/destructure.yue +++ b/spec/inputs/unicode/destructure.yue | |||
@@ -84,7 +84,7 @@ do | |||
84 | -- | 84 | -- |
85 | 85 | ||
86 | do | 86 | do |
87 | with {ε η΄ a,ε η΄ b} = δΈθ₯Ώ | 87 | with {ε η΄ a,ε η΄ b} := δΈθ₯Ώ |
88 | ζε° ε η΄ a, ε η΄ b | 88 | ζε° ε η΄ a, ε η΄ b |
89 | 89 | ||
90 | 90 | ||
diff --git a/spec/inputs/unicode/macro_export.yue b/spec/inputs/unicode/macro_export.yue index 3c9a942..56571cd 100644 --- a/spec/inputs/unicode/macro_export.yue +++ b/spec/inputs/unicode/macro_export.yue | |||
@@ -37,8 +37,8 @@ export macro ε€εΆ = (ζΊ, ηζ , ...)-> | |||
37 | " | 37 | " |
38 | do | 38 | do |
39 | local _ζΊ_, _ηζ _ | 39 | local _ζΊ_, _ηζ _ |
40 | with _ηζ _ = #{ηζ } | 40 | with _ηζ _ := #{ηζ } |
41 | with _ζΊ_ = #{ζΊ} | 41 | with _ζΊ_ := #{ζΊ} |
42 | #{table.concat for εζ΅ in *{...} do " | 42 | #{table.concat for εζ΅ in *{...} do " |
43 | _ηζ _.#{εζ΅} = _ζΊ_.#{εζ΅} | 43 | _ηζ _.#{εζ΅} = _ζΊ_.#{εζ΅} |
44 | "}" | 44 | "}" |
diff --git a/spec/inputs/unicode/with.yue b/spec/inputs/unicode/with.yue index ecbfdab..3c15add 100644 --- a/spec/inputs/unicode/with.yue +++ b/spec/inputs/unicode/with.yue | |||
@@ -45,19 +45,19 @@ do | |||
45 | with ειa | 45 | with ειa |
46 | ζε° .δΈη | 46 | ζε° .δΈη |
47 | 47 | ||
48 | 樑ε = with _樑ε = {} | 48 | 樑ε = with _樑ε := {} |
49 | .δΊη© = "δ½ ε₯½" | 49 | .δΊη© = "δ½ ε₯½" |
50 | 50 | ||
51 | with ειa, ειb = δΈθ₯Ώ, εΈ | 51 | with ειa, ειb := δΈθ₯Ώ, εΈ |
52 | ζε° .δΈη | 52 | ζε° .δΈη |
53 | 53 | ||
54 | ειx = with ειa, ειb = 1, 2 | 54 | ειx = with ειa, ειb := 1, 2 |
55 | ζε° ειa + ειb | 55 | ζε° ειa + ειb |
56 | 56 | ||
57 | ζε° with ειa, ειb = 1, 2 | 57 | ζε° with ειa, ειb := 1, 2 |
58 | ζε° ειa + ειb | 58 | ζε° ειa + ειb |
59 | 59 | ||
60 | p = with δ½ ε₯½!.εζ΅x, δΈη!.εζ΅y = 1, 2 | 60 | p = with δ½ ε₯½!.εζ΅x, δΈη!.εζ΅y := 1, 2 |
61 | ζε° ειa + ειb | 61 | ζε° ειa + ειb |
62 | 62 | ||
63 | -- | 63 | -- |
@@ -68,16 +68,16 @@ do | |||
68 | ειx\ε€§ε! | 68 | ειx\ε€§ε! |
69 | 69 | ||
70 | do | 70 | do |
71 | with ειk = "δΉ" | 71 | with ειk := "δΉ" |
72 | ζε° \ε€§ε! | 72 | ζε° \ε€§ε! |
73 | 73 | ||
74 | do | 74 | do |
75 | with ειa,ειb,ειc = "", "", "" | 75 | with ειa,ειb,ειc := "", "", "" |
76 | ζε° \ε€§ε! | 76 | ζε° \ε€§ε! |
77 | 77 | ||
78 | do | 78 | do |
79 | ειa = "εΊιΊ" | 79 | ειa = "εΊιΊ" |
80 | with ειa,ειb,ειc = "", "", "" | 80 | with ειa,ειb,ειc := "", "", "" |
81 | ζε° \ε€§ε! | 81 | ζε° \ε€§ε! |
82 | 82 | ||
83 | do | 83 | do |
@@ -85,7 +85,7 @@ do | |||
85 | ζε° \ε€§ε! | 85 | ζε° \ε€§ε! |
86 | 86 | ||
87 | do | 87 | do |
88 | with ειk.ειj = "δΉ" | 88 | with ειk.ειj := "δΉ" |
89 | ζε° \ε€§ε! | 89 | ζε° \ε€§ε! |
90 | 90 | ||
91 | do | 91 | do |
@@ -96,7 +96,7 @@ do | |||
96 | 96 | ||
97 | do | 97 | do |
98 | with ειa | 98 | with ειa |
99 | with .b = 2 | 99 | with .b := 2 |
100 | ζε° .c | 100 | ζε° .c |
101 | 101 | ||
102 | do | 102 | do |
@@ -131,12 +131,12 @@ do | |||
131 | 131 | ||
132 | do | 132 | do |
133 | global ζ©η | 133 | global ζ©η |
134 | with? ζ©η = εεΏη©ε½’ ε½: w, ι«: h, ι’θ²: 0x66000000 | 134 | with? ζ©η := εεΏη©ε½’ ε½: w, ι«: h, ι’θ²: 0x66000000 |
135 | .触ζΈε―η¨ = true | 135 | .触ζΈε―η¨ = true |
136 | .εε¬θ§¦ζΈ = true | 136 | .εε¬θ§¦ζΈ = true |
137 | 137 | ||
138 | do | 138 | do |
139 | with? ζ©η = εεΏη©ε½’ ε½: w, ι«: h, ι’θ²: 0x66000000 | 139 | with? ζ©η := εεΏη©ε½’ ε½: w, ι«: h, ι’θ²: 0x66000000 |
140 | .触ζΈε―η¨ = true | 140 | .触ζΈε―η¨ = true |
141 | .εε¬θ§¦ζΈ = true | 141 | .εε¬θ§¦ζΈ = true |
142 | 142 | ||
diff --git a/spec/inputs/with.yue b/spec/inputs/with.yue index 19b7be1..2256833 100644 --- a/spec/inputs/with.yue +++ b/spec/inputs/with.yue | |||
@@ -48,21 +48,21 @@ do | |||
48 | with a -- only one value allowed | 48 | with a -- only one value allowed |
49 | print .world | 49 | print .world |
50 | 50 | ||
51 | mod = with _M = {} | 51 | mod = with _M := {} |
52 | .Thing = "hi" | 52 | .Thing = "hi" |
53 | 53 | ||
54 | -- operate on a only | 54 | -- operate on a only |
55 | with a, b = something, pooh | 55 | with a, b := something, pooh |
56 | print .world | 56 | print .world |
57 | 57 | ||
58 | x = with a, b = 1, 2 | 58 | x = with a, b := 1, 2 |
59 | print a + b | 59 | print a + b |
60 | 60 | ||
61 | print with a, b = 1, 2 | 61 | print with a, b := 1, 2 |
62 | print a + b | 62 | print a + b |
63 | 63 | ||
64 | -- assignment lhs must be evaluated in the order they appear | 64 | -- assignment lhs must be evaluated in the order they appear |
65 | p = with hello!.x, world!.y = 1, 2 | 65 | p = with hello!.x, world!.y := 1, 2 |
66 | print a + b | 66 | print a + b |
67 | 67 | ||
68 | -- | 68 | -- |
@@ -73,16 +73,16 @@ do | |||
73 | x\upper! | 73 | x\upper! |
74 | 74 | ||
75 | do | 75 | do |
76 | with k = "jo" | 76 | with k := "jo" |
77 | print \upper! | 77 | print \upper! |
78 | 78 | ||
79 | do | 79 | do |
80 | with a,b,c = "", "", "" | 80 | with a,b,c := "", "", "" |
81 | print \upper! | 81 | print \upper! |
82 | 82 | ||
83 | do | 83 | do |
84 | a = "bunk" | 84 | a = "bunk" |
85 | with a,b,c = "", "", "" | 85 | with a,b,c := "", "", "" |
86 | print \upper! | 86 | print \upper! |
87 | 87 | ||
88 | do | 88 | do |
@@ -90,7 +90,7 @@ do | |||
90 | print \upper! | 90 | print \upper! |
91 | 91 | ||
92 | do | 92 | do |
93 | with k.j = "jo" | 93 | with k.j := "jo" |
94 | print \upper! | 94 | print \upper! |
95 | 95 | ||
96 | do | 96 | do |
@@ -103,7 +103,7 @@ do | |||
103 | do | 103 | do |
104 | with a | 104 | with a |
105 | -- nested `with`s with assignments should change the scope correctly | 105 | -- nested `with`s with assignments should change the scope correctly |
106 | with .b = 2 | 106 | with .b := 2 |
107 | print .c | 107 | print .c |
108 | 108 | ||
109 | do | 109 | do |
@@ -138,12 +138,12 @@ do | |||
138 | 138 | ||
139 | do | 139 | do |
140 | global mask | 140 | global mask |
141 | with? mask = SolidRect width: w, height: h, color: 0x66000000 | 141 | with? mask := SolidRect width: w, height: h, color: 0x66000000 |
142 | .touchEnabled = true | 142 | .touchEnabled = true |
143 | .swallowTouches = true | 143 | .swallowTouches = true |
144 | 144 | ||
145 | do | 145 | do |
146 | with? mask = SolidRect width: w, height: h, color: 0x66000000 | 146 | with? mask := SolidRect width: w, height: h, color: 0x66000000 |
147 | .touchEnabled = true | 147 | .touchEnabled = true |
148 | .swallowTouches = true | 148 | .swallowTouches = true |
149 | 149 | ||
@@ -152,4 +152,22 @@ do | |||
152 | return with {} | 152 | return with {} |
153 | return [123] | 153 | return [123] |
154 | 154 | ||
155 | do | ||
156 | f with item | ||
157 | if .id > 0 | ||
158 | break .content | ||
159 | |||
160 | a = with tb | ||
161 | if .v | ||
162 | break .a | ||
163 | |||
164 | a = while true | ||
165 | break with? tb | ||
166 | break 1 | ||
167 | |||
168 | do | ||
169 | a = for i = 1, 100 | ||
170 | with? x := tb[i] | ||
171 | break x if .id := 1 | ||
172 | |||
155 | nil | 173 | nil |
diff --git a/spec/outputs/5.1/loops.lua b/spec/outputs/5.1/loops.lua index 57b19be..e4f2871 100644 --- a/spec/outputs/5.1/loops.lua +++ b/spec/outputs/5.1/loops.lua | |||
@@ -60,8 +60,8 @@ do | |||
60 | local y = hello[_index_0] | 60 | local y = hello[_index_0] |
61 | if y % 2 == 0 then | 61 | if y % 2 == 0 then |
62 | _accum_0[_len_0] = y | 62 | _accum_0[_len_0] = y |
63 | _len_0 = _len_0 + 1 | ||
63 | end | 64 | end |
64 | _len_0 = _len_0 + 1 | ||
65 | end | 65 | end |
66 | x = _accum_0 | 66 | x = _accum_0 |
67 | end | 67 | end |
@@ -132,13 +132,11 @@ do | |||
132 | end | 132 | end |
133 | do | 133 | do |
134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
135 | local _len_0 = 1 | ||
136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
138 | local thing = _list_2[_index_0] | 137 | local thing = _list_2[_index_0] |
139 | y = "hello" | 138 | y = "hello" |
140 | break | 139 | break |
141 | _len_0 = _len_0 + 1 | ||
142 | end | 140 | end |
143 | x = _accum_0 | 141 | x = _accum_0 |
144 | end | 142 | end |
@@ -489,3 +487,131 @@ do | |||
489 | end | 487 | end |
490 | until false | 488 | until false |
491 | end | 489 | end |
490 | local _anon_func_0 = function(i, tb) | ||
491 | local _accum_0 = { } | ||
492 | local _len_0 = 1 | ||
493 | while tb[i] do | ||
494 | i = i + 1 | ||
495 | _accum_0[_len_0] = i - 1 | ||
496 | _len_0 = _len_0 + 1 | ||
497 | end | ||
498 | return _accum_0 | ||
499 | end | ||
500 | do | ||
501 | local index | ||
502 | do | ||
503 | local _accum_0 | ||
504 | for i = 1, #tb do | ||
505 | if tb[i] then | ||
506 | _accum_0 = i | ||
507 | break | ||
508 | end | ||
509 | end | ||
510 | index = _accum_0 | ||
511 | end | ||
512 | f((function() | ||
513 | local _accum_0 | ||
514 | for i = 1, #tb do | ||
515 | if tb[i] then | ||
516 | _accum_0 = i | ||
517 | break | ||
518 | end | ||
519 | end | ||
520 | return _accum_0 | ||
521 | end)()) | ||
522 | f((function() | ||
523 | local _accum_0 = { } | ||
524 | local _len_0 = 1 | ||
525 | for i = 1, #tb do | ||
526 | if tb[i] then | ||
527 | _accum_0[_len_0] = i | ||
528 | _len_0 = _len_0 + 1 | ||
529 | end | ||
530 | end | ||
531 | return _accum_0 | ||
532 | end)()) | ||
533 | i = 1 | ||
534 | local ids | ||
535 | do | ||
536 | local _accum_0 = { } | ||
537 | local _len_0 = 1 | ||
538 | while tb[i] do | ||
539 | i = i + 1 | ||
540 | _accum_0[_len_0] = i - 1 | ||
541 | _len_0 = _len_0 + 1 | ||
542 | end | ||
543 | ids = _accum_0 | ||
544 | end | ||
545 | i = 1 | ||
546 | local idx | ||
547 | do | ||
548 | local _accum_0 | ||
549 | while tb[i] do | ||
550 | i = i + 1 | ||
551 | _accum_0 = i - 1 | ||
552 | break | ||
553 | end | ||
554 | idx = _accum_0 | ||
555 | end | ||
556 | local f1 | ||
557 | f1 = function() | ||
558 | i = 1 | ||
559 | return f(_anon_func_0(i, tb)) | ||
560 | end | ||
561 | i = 1 | ||
562 | f((function() | ||
563 | local _accum_0 | ||
564 | while tb[i] do | ||
565 | i = i + 1 | ||
566 | _accum_0 = i - 1 | ||
567 | break | ||
568 | end | ||
569 | return _accum_0 | ||
570 | end)()) | ||
571 | local _accum_0 = { } | ||
572 | local _len_0 = 1 | ||
573 | local _list_3 = items | ||
574 | for _index_0 = 1, #_list_3 do | ||
575 | local item = _list_3[_index_0] | ||
576 | local _type_0 = type(item) | ||
577 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
578 | if _tab_0 then | ||
579 | local value = item.value | ||
580 | if "A" == item.type and value ~= nil then | ||
581 | if value > 5 then | ||
582 | _accum_0[_len_0] = item | ||
583 | _len_0 = _len_0 + 1 | ||
584 | end | ||
585 | end | ||
586 | end | ||
587 | end | ||
588 | list = _accum_0 | ||
589 | end | ||
590 | do | ||
591 | repeat | ||
592 | print(1) | ||
593 | until true | ||
594 | do | ||
595 | local _accum_0 | ||
596 | repeat | ||
597 | a = func() | ||
598 | _accum_0 = a.x | ||
599 | break | ||
600 | until a.v | ||
601 | x = _accum_0 | ||
602 | end | ||
603 | local items | ||
604 | local _accum_0 = { } | ||
605 | local _len_0 = 1 | ||
606 | repeat | ||
607 | local item = getItem() | ||
608 | if not item then | ||
609 | break | ||
610 | end | ||
611 | if item.value > 0 then | ||
612 | _accum_0[_len_0] = item | ||
613 | _len_0 = _len_0 + 1 | ||
614 | end | ||
615 | until false | ||
616 | items = _accum_0 | ||
617 | end | ||
diff --git a/spec/outputs/5.1/try_catch.lua b/spec/outputs/5.1/try_catch.lua index efd92c6..d2b58bc 100644 --- a/spec/outputs/5.1/try_catch.lua +++ b/spec/outputs/5.1/try_catch.lua | |||
@@ -22,6 +22,43 @@ end | |||
22 | local _anon_func_7 = function(a, b, c, tb) | 22 | local _anon_func_7 = function(a, b, c, tb) |
23 | return tb.f(a, b, c) | 23 | return tb.f(a, b, c) |
24 | end | 24 | end |
25 | local _anon_func_8 = function(_arg_0, ...) | ||
26 | local ok = _arg_0 | ||
27 | return ... | ||
28 | end | ||
29 | local _anon_func_10 = function(_arg_0, ...) | ||
30 | local _ok_0 = _arg_0 | ||
31 | if _ok_0 then | ||
32 | return ... | ||
33 | end | ||
34 | end | ||
35 | local _anon_func_9 = function(func, pcall) | ||
36 | return _anon_func_10(pcall(func)) | ||
37 | end | ||
38 | local _anon_func_12 = function(_arg_0, ...) | ||
39 | local _ok_0 = _arg_0 | ||
40 | if _ok_0 then | ||
41 | return ... | ||
42 | end | ||
43 | end | ||
44 | local _anon_func_11 = function(func, pcall) | ||
45 | return _anon_func_12(pcall(func)) | ||
46 | end | ||
47 | local _anon_func_14 = function(_arg_0, ...) | ||
48 | local _ok_0 = _arg_0 | ||
49 | if _ok_0 then | ||
50 | return ... | ||
51 | end | ||
52 | end | ||
53 | local _anon_func_13 = function(func, print, xpcall) | ||
54 | return _anon_func_14(xpcall(function() | ||
55 | print(123) | ||
56 | return func() | ||
57 | end, function(e) | ||
58 | print(e) | ||
59 | return e | ||
60 | end)) | ||
61 | end | ||
25 | local f | 62 | local f |
26 | f = function() | 63 | f = function() |
27 | xpcall(function() | 64 | xpcall(function() |
@@ -104,10 +141,236 @@ f = function() | |||
104 | do | 141 | do |
105 | x(function() | 142 | x(function() |
106 | local tb, a, b, c | 143 | local tb, a, b, c |
107 | f = function() | 144 | local f1 |
145 | f1 = function() | ||
108 | return pcall(_anon_func_7, a, b, c, tb) | 146 | return pcall(_anon_func_7, a, b, c, tb) |
109 | end | 147 | end |
110 | end) | 148 | end) |
111 | end | 149 | end |
150 | do | ||
151 | local f1 | ||
152 | f1 = function() | ||
153 | do | ||
154 | return _anon_func_8(pcall(function() | ||
155 | return func() | ||
156 | end)) | ||
157 | end | ||
158 | end | ||
159 | end | ||
160 | do | ||
161 | local func | ||
162 | local a, b, c | ||
163 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
164 | if _ok_0 then | ||
165 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
166 | end | ||
167 | end | ||
168 | do | ||
169 | local a, b, c | ||
170 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
171 | return func() | ||
172 | end) | ||
173 | if _ok_0 then | ||
174 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
175 | end | ||
176 | end | ||
177 | do | ||
178 | local a | ||
179 | local _exp_0 = (_anon_func_9(func, pcall)) | ||
180 | if _exp_0 ~= nil then | ||
181 | a = _exp_0 | ||
182 | else | ||
183 | a = "default" | ||
184 | end | ||
185 | end | ||
186 | do | ||
187 | f(_anon_func_11(func, pcall)) | ||
188 | end | ||
189 | do | ||
190 | f(_anon_func_13(func, print, xpcall)) | ||
191 | end | ||
112 | return nil | 192 | return nil |
113 | end | 193 | end |
194 | local _anon_func_15 = function(a, b, c, tb) | ||
195 | return tb.f(a, b, c) | ||
196 | end | ||
197 | local _anon_func_16 = function(_arg_0, ...) | ||
198 | local ok = _arg_0 | ||
199 | return ... | ||
200 | end | ||
201 | do | ||
202 | xpcall(function() | ||
203 | return func(1, 2, 3) | ||
204 | end, function(err) | ||
205 | return print(err) | ||
206 | end) | ||
207 | xpcall(function() | ||
208 | return func(1, 2, 3) | ||
209 | end, function(err) | ||
210 | return print(err) | ||
211 | end) | ||
212 | pcall(function() | ||
213 | print("trying") | ||
214 | return func(1, 2, 3) | ||
215 | end) | ||
216 | do | ||
217 | local success, result = xpcall(function() | ||
218 | return func(1, 2, 3) | ||
219 | end, function(err) | ||
220 | return print(err) | ||
221 | end) | ||
222 | success, result = pcall(function() | ||
223 | return func(1, 2, 3) | ||
224 | end) | ||
225 | end | ||
226 | local tb = { } | ||
227 | pcall(function() | ||
228 | return tb.func | ||
229 | end) | ||
230 | pcall(function() | ||
231 | return tb.func() | ||
232 | end) | ||
233 | pcall(function() | ||
234 | return tb.func() | ||
235 | end) | ||
236 | pcall(function() | ||
237 | return (tb.func()) | ||
238 | end) | ||
239 | pcall(function() | ||
240 | return (tb:func(1, 2, 3)) | ||
241 | end) | ||
242 | pcall(function() | ||
243 | return tb.func(1) | ||
244 | end) | ||
245 | pcall(function() | ||
246 | return tb.func(1) | ||
247 | end) | ||
248 | if (xpcall(function() | ||
249 | return func(1) | ||
250 | end, function(err) | ||
251 | return print(err) | ||
252 | end)) then | ||
253 | print("OK") | ||
254 | end | ||
255 | if xpcall(function() | ||
256 | return (func(1)) | ||
257 | end, function(err) | ||
258 | return print(err) | ||
259 | end) then | ||
260 | print("OK") | ||
261 | end | ||
262 | do | ||
263 | do | ||
264 | local success, result = pcall(function() | ||
265 | return func("abc", 123) | ||
266 | end) | ||
267 | if success then | ||
268 | print(result) | ||
269 | end | ||
270 | end | ||
271 | local success, result = xpcall(function() | ||
272 | return func("abc", 123) | ||
273 | end, function(err) | ||
274 | return print(err) | ||
275 | end) | ||
276 | success, result = xpcall(function() | ||
277 | return func("abc", 123) | ||
278 | end, function(err) | ||
279 | return print(err) | ||
280 | end) | ||
281 | if success then | ||
282 | print(result) | ||
283 | end | ||
284 | end | ||
285 | do | ||
286 | pcall(function() | ||
287 | return func(1, 2, 3) | ||
288 | end) | ||
289 | pcall(function() | ||
290 | return func(1, 2, 3) | ||
291 | end) | ||
292 | end | ||
293 | do | ||
294 | x(function() | ||
295 | local tb, a, b, c | ||
296 | local f1 | ||
297 | f1 = function() | ||
298 | return pcall(_anon_func_15, a, b, c, tb) | ||
299 | end | ||
300 | end) | ||
301 | end | ||
302 | do | ||
303 | local f1 | ||
304 | f1 = function() | ||
305 | do | ||
306 | return _anon_func_16(pcall(function() | ||
307 | return func() | ||
308 | end)) | ||
309 | end | ||
310 | end | ||
311 | end | ||
312 | do | ||
313 | local func | ||
314 | local a, b, c | ||
315 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
316 | if _ok_0 then | ||
317 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
318 | end | ||
319 | end | ||
320 | do | ||
321 | local a, b, c | ||
322 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
323 | return func() | ||
324 | end) | ||
325 | if _ok_0 then | ||
326 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
327 | end | ||
328 | end | ||
329 | do | ||
330 | local a | ||
331 | local _exp_0 = ((function() | ||
332 | return (function(_arg_0, ...) | ||
333 | local _ok_0 = _arg_0 | ||
334 | if _ok_0 then | ||
335 | return ... | ||
336 | end | ||
337 | end)(pcall(function() | ||
338 | return func() | ||
339 | end)) | ||
340 | end)()) | ||
341 | if _exp_0 ~= nil then | ||
342 | a = _exp_0 | ||
343 | else | ||
344 | a = "default" | ||
345 | end | ||
346 | end | ||
347 | do | ||
348 | f((function() | ||
349 | return (function(_arg_0, ...) | ||
350 | local _ok_0 = _arg_0 | ||
351 | if _ok_0 then | ||
352 | return ... | ||
353 | end | ||
354 | end)(pcall(function() | ||
355 | return func() | ||
356 | end)) | ||
357 | end)()) | ||
358 | end | ||
359 | do | ||
360 | f((function() | ||
361 | return (function(_arg_0, ...) | ||
362 | local _ok_0 = _arg_0 | ||
363 | if _ok_0 then | ||
364 | return ... | ||
365 | end | ||
366 | end)(xpcall(function() | ||
367 | print(123) | ||
368 | return func() | ||
369 | end, function(e) | ||
370 | print(e) | ||
371 | return e | ||
372 | end)) | ||
373 | end)()) | ||
374 | end | ||
375 | end | ||
376 | return nil | ||
diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua index 162c5a8..89c5f8a 100644 --- a/spec/outputs/assign.lua +++ b/spec/outputs/assign.lua | |||
@@ -43,10 +43,8 @@ do | |||
43 | end | 43 | end |
44 | end | 44 | end |
45 | local _anon_func_0 = function(print) | 45 | local _anon_func_0 = function(print) |
46 | do | 46 | print(123) |
47 | print(123) | 47 | return { } |
48 | return { } | ||
49 | end | ||
50 | end | 48 | end |
51 | return _(function() | 49 | return _(function() |
52 | setmetatable(a, _anon_func_0(print)) | 50 | setmetatable(a, _anon_func_0(print)) |
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua index 27f8de5..b7d1236 100644 --- a/spec/outputs/codes_from_doc.lua +++ b/spec/outputs/codes_from_doc.lua | |||
@@ -20,6 +20,38 @@ local inventory = { | |||
20 | } | 20 | } |
21 | } | 21 | } |
22 | } | 22 | } |
23 | local map | ||
24 | map = function(arr, action) | ||
25 | local _accum_0 = { } | ||
26 | local _len_0 = 1 | ||
27 | for _index_0 = 1, #arr do | ||
28 | local item = arr[_index_0] | ||
29 | _accum_0[_len_0] = action(item) | ||
30 | _len_0 = _len_0 + 1 | ||
31 | end | ||
32 | return _accum_0 | ||
33 | end | ||
34 | local filter | ||
35 | filter = function(arr, cond) | ||
36 | local _accum_0 = { } | ||
37 | local _len_0 = 1 | ||
38 | for _index_0 = 1, #arr do | ||
39 | local item = arr[_index_0] | ||
40 | if cond(item) then | ||
41 | _accum_0[_len_0] = item | ||
42 | _len_0 = _len_0 + 1 | ||
43 | end | ||
44 | end | ||
45 | return _accum_0 | ||
46 | end | ||
47 | local reduce | ||
48 | reduce = function(arr, init, action) | ||
49 | for _index_0 = 1, #arr do | ||
50 | local item = arr[_index_0] | ||
51 | init = action(init, item) | ||
52 | end | ||
53 | return init | ||
54 | end | ||
23 | print(reduce(filter(map({ | 55 | print(reduce(filter(map({ |
24 | 1, | 56 | 1, |
25 | 2, | 57 | 2, |
@@ -77,6 +109,12 @@ end | |||
77 | print("yuescript") | 109 | print("yuescript") |
78 | print(3) | 110 | print(3) |
79 | print("Valid enum type:", "Static") | 111 | print("Valid enum type:", "Static") |
112 | do | ||
113 | print(123, "hello") | ||
114 | end | ||
115 | do | ||
116 | print(123, "hello") | ||
117 | end | ||
80 | if tb ~= nil then | 118 | if tb ~= nil then |
81 | tb:func() | 119 | tb:func() |
82 | end | 120 | end |
@@ -177,6 +215,16 @@ for _key_0, _value_0 in pairs(b) do | |||
177 | end | 215 | end |
178 | end | 216 | end |
179 | merge = _tab_0 | 217 | merge = _tab_0 |
218 | local last | ||
219 | do | ||
220 | local _item_0 = data.items | ||
221 | last = _item_0[#_item_0] | ||
222 | end | ||
223 | local second_last | ||
224 | do | ||
225 | local _item_0 = data.items | ||
226 | second_last = _item_0[#_item_0 - 1] | ||
227 | end | ||
180 | local mt = { } | 228 | local mt = { } |
181 | local add | 229 | local add |
182 | add = function(self, right) | 230 | add = function(self, right) |
@@ -307,6 +355,14 @@ func({ | |||
307 | 2, | 355 | 2, |
308 | 3 | 356 | 3 |
309 | }) | 357 | }) |
358 | local f | ||
359 | f = function() | ||
360 | return { | ||
361 | 1, | ||
362 | 2, | ||
363 | 3 | ||
364 | } | ||
365 | end | ||
310 | local tb = { | 366 | local tb = { |
311 | name = "abc", | 367 | name = "abc", |
312 | values = { | 368 | values = { |
@@ -547,6 +603,59 @@ end | |||
547 | local two, four | 603 | local two, four |
548 | local _obj_0 = items | 604 | local _obj_0 = items |
549 | two, four = _obj_0[2], _obj_0[4] | 605 | two, four = _obj_0[2], _obj_0[4] |
606 | local orders = { | ||
607 | "first", | ||
608 | "second", | ||
609 | "third", | ||
610 | "fourth", | ||
611 | "last" | ||
612 | } | ||
613 | local first, bulk, last = orders[1], (function() | ||
614 | local _accum_0 = { } | ||
615 | local _len_0 = 1 | ||
616 | local _max_0 = #orders + -2 + 1 | ||
617 | for _index_0 = 2, _max_0 do | ||
618 | local _item_0 = orders[_index_0] | ||
619 | _accum_0[_len_0] = _item_0 | ||
620 | _len_0 = _len_0 + 1 | ||
621 | end | ||
622 | return _accum_0 | ||
623 | end)(), orders[#orders] | ||
624 | print(first) | ||
625 | print(bulk) | ||
626 | print(last) | ||
627 | local first, rest | ||
628 | do | ||
629 | local _obj_0 = orders | ||
630 | first, rest = _obj_0[1], (function() | ||
631 | local _accum_0 = { } | ||
632 | local _len_0 = 1 | ||
633 | local _max_0 = #_obj_0 | ||
634 | for _index_0 = 2, _max_0 do | ||
635 | local _item_0 = _obj_0[_index_0] | ||
636 | _accum_0[_len_0] = _item_0 | ||
637 | _len_0 = _len_0 + 1 | ||
638 | end | ||
639 | return _accum_0 | ||
640 | end)() | ||
641 | end | ||
642 | local start, last | ||
643 | do | ||
644 | local _obj_0 = orders | ||
645 | start, last = (function() | ||
646 | local _accum_0 = { } | ||
647 | local _len_0 = 1 | ||
648 | local _max_0 = #_obj_0 + -2 + 1 | ||
649 | for _index_0 = 1, _max_0 do | ||
650 | local _item_0 = _obj_0[_index_0] | ||
651 | _accum_0[_len_0] = _item_0 | ||
652 | _len_0 = _len_0 + 1 | ||
653 | end | ||
654 | return _accum_0 | ||
655 | end)(), _obj_0[#_obj_0] | ||
656 | end | ||
657 | local _obj_0 = orders | ||
658 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
550 | local tuples = { | 659 | local tuples = { |
551 | { | 660 | { |
552 | "hello", | 661 | "hello", |
@@ -648,6 +757,56 @@ end) | |||
648 | if success then | 757 | if success then |
649 | print(result) | 758 | print(result) |
650 | end | 759 | end |
760 | local a, b, c | ||
761 | do | ||
762 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
763 | return func() | ||
764 | end) | ||
765 | if _ok_0 then | ||
766 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
767 | end | ||
768 | end | ||
769 | do | ||
770 | local _exp_0 = ((function() | ||
771 | return (function(_arg_0, ...) | ||
772 | local _ok_0 = _arg_0 | ||
773 | if _ok_0 then | ||
774 | return ... | ||
775 | end | ||
776 | end)(pcall(function() | ||
777 | return func() | ||
778 | end)) | ||
779 | end)()) | ||
780 | if _exp_0 ~= nil then | ||
781 | a = _exp_0 | ||
782 | else | ||
783 | a = "default" | ||
784 | end | ||
785 | end | ||
786 | f((function() | ||
787 | return (function(_arg_0, ...) | ||
788 | local _ok_0 = _arg_0 | ||
789 | if _ok_0 then | ||
790 | return ... | ||
791 | end | ||
792 | end)(pcall(function() | ||
793 | return func() | ||
794 | end)) | ||
795 | end)()) | ||
796 | f((function() | ||
797 | return (function(_arg_0, ...) | ||
798 | local _ok_0 = _arg_0 | ||
799 | if _ok_0 then | ||
800 | return ... | ||
801 | end | ||
802 | end)(xpcall(function() | ||
803 | print(123) | ||
804 | return func() | ||
805 | end, function(e) | ||
806 | print(e) | ||
807 | return e | ||
808 | end)) | ||
809 | end)()) | ||
651 | local a <const> = 123 | 810 | local a <const> = 123 |
652 | local _ <close> = setmetatable({ }, { | 811 | local _ <close> = setmetatable({ }, { |
653 | __close = function() | 812 | __close = function() |
@@ -657,10 +816,19 @@ local _ <close> = setmetatable({ }, { | |||
657 | local a, b, c, d | 816 | local a, b, c, d |
658 | local _obj_0 = tb | 817 | local _obj_0 = tb |
659 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 818 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
819 | Constant = 123 | ||
660 | local some_string = "Here is a string\n that has a line break in it." | 820 | local some_string = "Here is a string\n that has a line break in it." |
661 | print("I am " .. tostring(math.random() * 100) .. "% sure.") | 821 | print("I am " .. tostring(math.random() * 100) .. "% sure.") |
662 | local integer = 1000000 | 822 | local integer = 1000000 |
663 | local hex = 0xEFBBBF | 823 | local hex = 0xEFBBBF |
824 | local binary = 19 | ||
825 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
826 | local fn | ||
827 | fn = function() | ||
828 | local str = "foo:\n bar: baz" | ||
829 | return str | ||
830 | end | ||
831 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
664 | local my_function | 832 | local my_function |
665 | my_function = function() end | 833 | my_function = function() end |
666 | my_function() | 834 | my_function() |
@@ -860,11 +1028,10 @@ for i, item in ipairs(items) do | |||
860 | _len_0 = _len_0 + 1 | 1028 | _len_0 = _len_0 + 1 |
861 | end | 1029 | end |
862 | doubled = _accum_0 | 1030 | doubled = _accum_0 |
863 | local iter = ipairs(items) | ||
864 | local slice | 1031 | local slice |
865 | local _accum_0 = { } | 1032 | local _accum_0 = { } |
866 | local _len_0 = 1 | 1033 | local _len_0 = 1 |
867 | for i, item in iter do | 1034 | for i, item in ipairs(items) do |
868 | if i > 1 and i < 3 then | 1035 | if i > 1 and i < 3 then |
869 | _accum_0[_len_0] = item | 1036 | _accum_0[_len_0] = item |
870 | _len_0 = _len_0 + 1 | 1037 | _len_0 = _len_0 + 1 |
@@ -971,8 +1138,7 @@ local slice | |||
971 | local _accum_0 = { } | 1138 | local _accum_0 = { } |
972 | local _len_0 = 1 | 1139 | local _len_0 = 1 |
973 | local _list_0 = items | 1140 | local _list_0 = items |
974 | local _max_0 = 5 | 1141 | for _index_0 = 1, 5 do |
975 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
976 | local item = _list_0[_index_0] | 1142 | local item = _list_0[_index_0] |
977 | _accum_0[_len_0] = item | 1143 | _accum_0[_len_0] = item |
978 | _len_0 = _len_0 + 1 | 1144 | _len_0 = _len_0 + 1 |
@@ -982,7 +1148,8 @@ local slice | |||
982 | local _accum_0 = { } | 1148 | local _accum_0 = { } |
983 | local _len_0 = 1 | 1149 | local _len_0 = 1 |
984 | local _list_0 = items | 1150 | local _list_0 = items |
985 | for _index_0 = 2, #_list_0 do | 1151 | local _max_0 = #_list_0 |
1152 | for _index_0 = 2, _max_0 do | ||
986 | local item = _list_0[_index_0] | 1153 | local item = _list_0[_index_0] |
987 | _accum_0[_len_0] = item | 1154 | _accum_0[_len_0] = item |
988 | _len_0 = _len_0 + 1 | 1155 | _len_0 = _len_0 + 1 |
@@ -992,12 +1159,46 @@ local slice | |||
992 | local _accum_0 = { } | 1159 | local _accum_0 = { } |
993 | local _len_0 = 1 | 1160 | local _len_0 = 1 |
994 | local _list_0 = items | 1161 | local _list_0 = items |
995 | for _index_0 = 1, #_list_0, 2 do | 1162 | local _max_0 = #_list_0 |
1163 | for _index_0 = 1, _max_0, 2 do | ||
996 | local item = _list_0[_index_0] | 1164 | local item = _list_0[_index_0] |
997 | _accum_0[_len_0] = item | 1165 | _accum_0[_len_0] = item |
998 | _len_0 = _len_0 + 1 | 1166 | _len_0 = _len_0 + 1 |
999 | end | 1167 | end |
1000 | slice = _accum_0 | 1168 | slice = _accum_0 |
1169 | local slice | ||
1170 | local _accum_0 = { } | ||
1171 | local _len_0 = 1 | ||
1172 | local _list_0 = items | ||
1173 | local _min_0 = #_list_0 + -4 + 1 | ||
1174 | local _max_0 = #_list_0 + -1 + 1 | ||
1175 | for _index_0 = _min_0, _max_0 do | ||
1176 | local item = _list_0[_index_0] | ||
1177 | _accum_0[_len_0] = item | ||
1178 | _len_0 = _len_0 + 1 | ||
1179 | end | ||
1180 | slice = _accum_0 | ||
1181 | local reverse_slice | ||
1182 | local _accum_0 = { } | ||
1183 | local _len_0 = 1 | ||
1184 | local _list_0 = items | ||
1185 | local _min_0 = #_list_0 + -1 + 1 | ||
1186 | for _index_0 = _min_0, 1, -1 do | ||
1187 | local item = _list_0[_index_0] | ||
1188 | _accum_0[_len_0] = item | ||
1189 | _len_0 = _len_0 + 1 | ||
1190 | end | ||
1191 | reverse_slice = _accum_0 | ||
1192 | local sub_list | ||
1193 | local _accum_0 = { } | ||
1194 | local _len_0 = 1 | ||
1195 | local _list_0 = items | ||
1196 | for _index_0 = 2, 4 do | ||
1197 | local _item_0 = _list_0[_index_0] | ||
1198 | _accum_0[_len_0] = _item_0 | ||
1199 | _len_0 = _len_0 + 1 | ||
1200 | end | ||
1201 | sub_list = _accum_0 | ||
1001 | for i = 10, 20 do | 1202 | for i = 10, 20 do |
1002 | print(i) | 1203 | print(i) |
1003 | end | 1204 | end |
@@ -1008,8 +1209,7 @@ for key, value in pairs(object) do | |||
1008 | print(key, value) | 1209 | print(key, value) |
1009 | end | 1210 | end |
1010 | local _list_0 = items | 1211 | local _list_0 = items |
1011 | local _max_0 = 4 | 1212 | for _index_0 = 2, 4 do |
1012 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
1013 | local item = _list_0[_index_0] | 1213 | local item = _list_0[_index_0] |
1014 | print(item) | 1214 | print(item) |
1015 | end | 1215 | end |
@@ -1027,12 +1227,24 @@ local _len_0 = 1 | |||
1027 | for i = 1, 20 do | 1227 | for i = 1, 20 do |
1028 | if i % 2 == 0 then | 1228 | if i % 2 == 0 then |
1029 | _accum_0[_len_0] = i * 2 | 1229 | _accum_0[_len_0] = i * 2 |
1230 | _len_0 = _len_0 + 1 | ||
1030 | else | 1231 | else |
1031 | _accum_0[_len_0] = i | 1232 | _accum_0[_len_0] = i |
1233 | _len_0 = _len_0 + 1 | ||
1032 | end | 1234 | end |
1033 | _len_0 = _len_0 + 1 | ||
1034 | end | 1235 | end |
1035 | doubled_evens = _accum_0 | 1236 | doubled_evens = _accum_0 |
1237 | local first_large | ||
1238 | local _accum_0 | ||
1239 | local _list_0 = numbers | ||
1240 | for _index_0 = 1, #_list_0 do | ||
1241 | local n = _list_0[_index_0] | ||
1242 | if n > 10 then | ||
1243 | _accum_0 = n | ||
1244 | break | ||
1245 | end | ||
1246 | end | ||
1247 | first_large = _accum_0 | ||
1036 | local func_a | 1248 | local func_a |
1037 | func_a = function() | 1249 | func_a = function() |
1038 | for i = 1, 10 do | 1250 | for i = 1, 10 do |
@@ -1181,7 +1393,7 @@ if "Robert" == name then | |||
1181 | elseif "Dan" == name or "Daniel" == name then | 1393 | elseif "Dan" == name or "Daniel" == name then |
1182 | print("Your name, it's Dan") | 1394 | print("Your name, it's Dan") |
1183 | else | 1395 | else |
1184 | print("I don't know about your name") | 1396 | print("I don't know about you with name " .. tostring(name)) |
1185 | end | 1397 | end |
1186 | local b = 1 | 1398 | local b = 1 |
1187 | local next_number | 1399 | local next_number |
@@ -1281,6 +1493,192 @@ if _tab_0 then | |||
1281 | end | 1493 | end |
1282 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 1494 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
1283 | end | 1495 | end |
1496 | local _exp_0 = tb | ||
1497 | local _type_0 = type(_exp_0) | ||
1498 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1499 | local _match_0 = false | ||
1500 | if _tab_0 then | ||
1501 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
1502 | _match_0 = true | ||
1503 | print("1, 2, 3") | ||
1504 | end | ||
1505 | end | ||
1506 | if not _match_0 then | ||
1507 | local _match_1 = false | ||
1508 | if _tab_0 then | ||
1509 | local b = _exp_0[2] | ||
1510 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
1511 | _match_1 = true | ||
1512 | print("1, " .. tostring(b) .. ", 3") | ||
1513 | end | ||
1514 | end | ||
1515 | if not _match_1 then | ||
1516 | if _tab_0 then | ||
1517 | local b = _exp_0[3] | ||
1518 | if b == nil then | ||
1519 | b = 3 | ||
1520 | end | ||
1521 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
1522 | print("1, 2, " .. tostring(b)) | ||
1523 | end | ||
1524 | end | ||
1525 | end | ||
1526 | end | ||
1527 | local _exp_0 = tb | ||
1528 | local _type_0 = type(_exp_0) | ||
1529 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1530 | local _match_0 = false | ||
1531 | if _tab_0 then | ||
1532 | local result = _exp_0.result | ||
1533 | if true == _exp_0.success and result ~= nil then | ||
1534 | _match_0 = true | ||
1535 | print("success", result) | ||
1536 | end | ||
1537 | end | ||
1538 | if not _match_0 then | ||
1539 | local _match_1 = false | ||
1540 | if _tab_0 then | ||
1541 | if false == _exp_0.success then | ||
1542 | _match_1 = true | ||
1543 | print("failed", result) | ||
1544 | end | ||
1545 | end | ||
1546 | if not _match_1 then | ||
1547 | print("invalid") | ||
1548 | end | ||
1549 | end | ||
1550 | local _exp_0 = tb | ||
1551 | local _type_0 = type(_exp_0) | ||
1552 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1553 | local _match_0 = false | ||
1554 | if _tab_0 then | ||
1555 | local content | ||
1556 | do | ||
1557 | local _obj_0 = _exp_0.data | ||
1558 | local _type_1 = type(_obj_0) | ||
1559 | if "table" == _type_1 or "userdata" == _type_1 then | ||
1560 | content = _obj_0.content | ||
1561 | end | ||
1562 | end | ||
1563 | local _val_0 | ||
1564 | do | ||
1565 | local _obj_0 = _exp_0.data | ||
1566 | if _obj_0 ~= nil then | ||
1567 | _val_0 = _obj_0.type | ||
1568 | end | ||
1569 | end | ||
1570 | if "success" == _val_0 and content ~= nil then | ||
1571 | _match_0 = true | ||
1572 | print("success", content) | ||
1573 | end | ||
1574 | end | ||
1575 | if not _match_0 then | ||
1576 | local _match_1 = false | ||
1577 | if _tab_0 then | ||
1578 | local content | ||
1579 | do | ||
1580 | local _obj_0 = _exp_0.data | ||
1581 | local _type_1 = type(_obj_0) | ||
1582 | if "table" == _type_1 or "userdata" == _type_1 then | ||
1583 | content = _obj_0.content | ||
1584 | end | ||
1585 | end | ||
1586 | local _val_0 | ||
1587 | do | ||
1588 | local _obj_0 = _exp_0.data | ||
1589 | if _obj_0 ~= nil then | ||
1590 | _val_0 = _obj_0.type | ||
1591 | end | ||
1592 | end | ||
1593 | if "error" == _val_0 and content ~= nil then | ||
1594 | _match_1 = true | ||
1595 | print("failed", content) | ||
1596 | end | ||
1597 | end | ||
1598 | if not _match_1 then | ||
1599 | print("invalid") | ||
1600 | end | ||
1601 | end | ||
1602 | local _exp_0 = tb | ||
1603 | local _type_0 = type(_exp_0) | ||
1604 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1605 | if _tab_0 then | ||
1606 | local fourth = _exp_0[4] | ||
1607 | local _val_0 | ||
1608 | do | ||
1609 | local _obj_0 = _exp_0[1] | ||
1610 | if _obj_0 ~= nil then | ||
1611 | _val_0 = _obj_0.a | ||
1612 | end | ||
1613 | end | ||
1614 | local _val_1 | ||
1615 | do | ||
1616 | local _obj_0 = _exp_0[1] | ||
1617 | if _obj_0 ~= nil then | ||
1618 | _val_1 = _obj_0.b | ||
1619 | end | ||
1620 | end | ||
1621 | local _val_2 | ||
1622 | do | ||
1623 | local _obj_0 = _exp_0[2] | ||
1624 | if _obj_0 ~= nil then | ||
1625 | _val_2 = _obj_0.a | ||
1626 | end | ||
1627 | end | ||
1628 | local _val_3 | ||
1629 | do | ||
1630 | local _obj_0 = _exp_0[2] | ||
1631 | if _obj_0 ~= nil then | ||
1632 | _val_3 = _obj_0.b | ||
1633 | end | ||
1634 | end | ||
1635 | local _val_4 | ||
1636 | do | ||
1637 | local _obj_0 = _exp_0[3] | ||
1638 | if _obj_0 ~= nil then | ||
1639 | _val_4 = _obj_0.a | ||
1640 | end | ||
1641 | end | ||
1642 | local _val_5 | ||
1643 | do | ||
1644 | local _obj_0 = _exp_0[3] | ||
1645 | if _obj_0 ~= nil then | ||
1646 | _val_5 = _obj_0.b | ||
1647 | end | ||
1648 | end | ||
1649 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
1650 | print("matched", fourth) | ||
1651 | end | ||
1652 | end | ||
1653 | local segments = { | ||
1654 | "admin", | ||
1655 | "users", | ||
1656 | "logs", | ||
1657 | "view" | ||
1658 | } | ||
1659 | local _type_0 = type(segments) | ||
1660 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1661 | if _tab_0 then | ||
1662 | local groups | ||
1663 | do | ||
1664 | local _accum_0 = { } | ||
1665 | local _len_0 = 1 | ||
1666 | local _max_0 = #segments + -3 + 1 | ||
1667 | for _index_0 = 1, _max_0 do | ||
1668 | local _item_0 = segments[_index_0] | ||
1669 | _accum_0[_len_0] = _item_0 | ||
1670 | _len_0 = _len_0 + 1 | ||
1671 | end | ||
1672 | groups = _accum_0 | ||
1673 | end | ||
1674 | local resource = segments[#segments - 1] | ||
1675 | local action = segments[#segments] | ||
1676 | if resource ~= nil and action ~= nil then | ||
1677 | print("Group:", groups) | ||
1678 | print("Resource:", resource) | ||
1679 | print("Action:", action) | ||
1680 | end | ||
1681 | end | ||
1284 | local Inventory | 1682 | local Inventory |
1285 | local _class_0 | 1683 | local _class_0 |
1286 | local _base_0 = { | 1684 | local _base_0 = { |
@@ -1937,6 +2335,10 @@ do | |||
1937 | _with_1["key-name"] = value | 2335 | _with_1["key-name"] = value |
1938 | end | 2336 | end |
1939 | _with_0[#_with_0 + 1] = "abc" | 2337 | _with_0[#_with_0 + 1] = "abc" |
2338 | local _with_0 = obj | ||
2339 | if _with_0 ~= nil then | ||
2340 | print(obj.name) | ||
2341 | end | ||
1940 | do | 2342 | do |
1941 | local var = "hello" | 2343 | local var = "hello" |
1942 | print(var) | 2344 | print(var) |
@@ -2027,6 +2429,38 @@ local inventory = { | |||
2027 | } | 2429 | } |
2028 | } | 2430 | } |
2029 | } | 2431 | } |
2432 | local map | ||
2433 | map = function(arr, action) | ||
2434 | local _accum_0 = { } | ||
2435 | local _len_0 = 1 | ||
2436 | for _index_0 = 1, #arr do | ||
2437 | local item = arr[_index_0] | ||
2438 | _accum_0[_len_0] = action(item) | ||
2439 | _len_0 = _len_0 + 1 | ||
2440 | end | ||
2441 | return _accum_0 | ||
2442 | end | ||
2443 | local filter | ||
2444 | filter = function(arr, cond) | ||
2445 | local _accum_0 = { } | ||
2446 | local _len_0 = 1 | ||
2447 | for _index_0 = 1, #arr do | ||
2448 | local item = arr[_index_0] | ||
2449 | if cond(item) then | ||
2450 | _accum_0[_len_0] = item | ||
2451 | _len_0 = _len_0 + 1 | ||
2452 | end | ||
2453 | end | ||
2454 | return _accum_0 | ||
2455 | end | ||
2456 | local reduce | ||
2457 | reduce = function(arr, init, action) | ||
2458 | for _index_0 = 1, #arr do | ||
2459 | local item = arr[_index_0] | ||
2460 | init = action(init, item) | ||
2461 | end | ||
2462 | return init | ||
2463 | end | ||
2030 | print(reduce(filter(map({ | 2464 | print(reduce(filter(map({ |
2031 | 1, | 2465 | 1, |
2032 | 2, | 2466 | 2, |
@@ -2084,6 +2518,12 @@ end | |||
2084 | print("yuescript") | 2518 | print("yuescript") |
2085 | print(3) | 2519 | print(3) |
2086 | print("Valid enum type:", "Static") | 2520 | print("Valid enum type:", "Static") |
2521 | do | ||
2522 | print(123, "hello") | ||
2523 | end | ||
2524 | do | ||
2525 | print(123, "hello") | ||
2526 | end | ||
2087 | if tb ~= nil then | 2527 | if tb ~= nil then |
2088 | tb:func() | 2528 | tb:func() |
2089 | end | 2529 | end |
@@ -2184,6 +2624,16 @@ for _key_0, _value_0 in pairs(b) do | |||
2184 | end | 2624 | end |
2185 | end | 2625 | end |
2186 | merge = _tab_0 | 2626 | merge = _tab_0 |
2627 | local last | ||
2628 | do | ||
2629 | local _item_0 = data.items | ||
2630 | last = _item_0[#_item_0] | ||
2631 | end | ||
2632 | local second_last | ||
2633 | do | ||
2634 | local _item_0 = data.items | ||
2635 | second_last = _item_0[#_item_0 - 1] | ||
2636 | end | ||
2187 | local mt = { } | 2637 | local mt = { } |
2188 | local add | 2638 | local add |
2189 | add = function(self, right) | 2639 | add = function(self, right) |
@@ -2314,6 +2764,14 @@ func({ | |||
2314 | 2, | 2764 | 2, |
2315 | 3 | 2765 | 3 |
2316 | }) | 2766 | }) |
2767 | local f | ||
2768 | f = function() | ||
2769 | return { | ||
2770 | 1, | ||
2771 | 2, | ||
2772 | 3 | ||
2773 | } | ||
2774 | end | ||
2317 | local tb = { | 2775 | local tb = { |
2318 | name = "abc", | 2776 | name = "abc", |
2319 | values = { | 2777 | values = { |
@@ -2554,6 +3012,59 @@ end | |||
2554 | local two, four | 3012 | local two, four |
2555 | local _obj_0 = items | 3013 | local _obj_0 = items |
2556 | two, four = _obj_0[2], _obj_0[4] | 3014 | two, four = _obj_0[2], _obj_0[4] |
3015 | local orders = { | ||
3016 | "first", | ||
3017 | "second", | ||
3018 | "third", | ||
3019 | "fourth", | ||
3020 | "last" | ||
3021 | } | ||
3022 | local first, bulk, last = orders[1], (function() | ||
3023 | local _accum_0 = { } | ||
3024 | local _len_0 = 1 | ||
3025 | local _max_0 = #orders + -2 + 1 | ||
3026 | for _index_0 = 2, _max_0 do | ||
3027 | local _item_0 = orders[_index_0] | ||
3028 | _accum_0[_len_0] = _item_0 | ||
3029 | _len_0 = _len_0 + 1 | ||
3030 | end | ||
3031 | return _accum_0 | ||
3032 | end)(), orders[#orders] | ||
3033 | print(first) | ||
3034 | print(bulk) | ||
3035 | print(last) | ||
3036 | local first, rest | ||
3037 | do | ||
3038 | local _obj_0 = orders | ||
3039 | first, rest = _obj_0[1], (function() | ||
3040 | local _accum_0 = { } | ||
3041 | local _len_0 = 1 | ||
3042 | local _max_0 = #_obj_0 | ||
3043 | for _index_0 = 2, _max_0 do | ||
3044 | local _item_0 = _obj_0[_index_0] | ||
3045 | _accum_0[_len_0] = _item_0 | ||
3046 | _len_0 = _len_0 + 1 | ||
3047 | end | ||
3048 | return _accum_0 | ||
3049 | end)() | ||
3050 | end | ||
3051 | local start, last | ||
3052 | do | ||
3053 | local _obj_0 = orders | ||
3054 | start, last = (function() | ||
3055 | local _accum_0 = { } | ||
3056 | local _len_0 = 1 | ||
3057 | local _max_0 = #_obj_0 + -2 + 1 | ||
3058 | for _index_0 = 1, _max_0 do | ||
3059 | local _item_0 = _obj_0[_index_0] | ||
3060 | _accum_0[_len_0] = _item_0 | ||
3061 | _len_0 = _len_0 + 1 | ||
3062 | end | ||
3063 | return _accum_0 | ||
3064 | end)(), _obj_0[#_obj_0] | ||
3065 | end | ||
3066 | local _obj_0 = orders | ||
3067 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
2557 | local tuples = { | 3068 | local tuples = { |
2558 | { | 3069 | { |
2559 | "hello", | 3070 | "hello", |
@@ -2655,6 +3166,56 @@ end) | |||
2655 | if success then | 3166 | if success then |
2656 | print(result) | 3167 | print(result) |
2657 | end | 3168 | end |
3169 | local a, b, c | ||
3170 | do | ||
3171 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
3172 | return func() | ||
3173 | end) | ||
3174 | if _ok_0 then | ||
3175 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
3176 | end | ||
3177 | end | ||
3178 | do | ||
3179 | local _exp_0 = ((function() | ||
3180 | return (function(_arg_0, ...) | ||
3181 | local _ok_0 = _arg_0 | ||
3182 | if _ok_0 then | ||
3183 | return ... | ||
3184 | end | ||
3185 | end)(pcall(function() | ||
3186 | return func() | ||
3187 | end)) | ||
3188 | end)()) | ||
3189 | if _exp_0 ~= nil then | ||
3190 | a = _exp_0 | ||
3191 | else | ||
3192 | a = "default" | ||
3193 | end | ||
3194 | end | ||
3195 | f((function() | ||
3196 | return (function(_arg_0, ...) | ||
3197 | local _ok_0 = _arg_0 | ||
3198 | if _ok_0 then | ||
3199 | return ... | ||
3200 | end | ||
3201 | end)(pcall(function() | ||
3202 | return func() | ||
3203 | end)) | ||
3204 | end)()) | ||
3205 | f((function() | ||
3206 | return (function(_arg_0, ...) | ||
3207 | local _ok_0 = _arg_0 | ||
3208 | if _ok_0 then | ||
3209 | return ... | ||
3210 | end | ||
3211 | end)(xpcall(function() | ||
3212 | print(123) | ||
3213 | return func() | ||
3214 | end, function(e) | ||
3215 | print(e) | ||
3216 | return e | ||
3217 | end)) | ||
3218 | end)()) | ||
2658 | local a <const> = 123 | 3219 | local a <const> = 123 |
2659 | local _ <close> = setmetatable({ }, { | 3220 | local _ <close> = setmetatable({ }, { |
2660 | __close = function() | 3221 | __close = function() |
@@ -2664,10 +3225,19 @@ local _ <close> = setmetatable({ }, { | |||
2664 | local a, b, c, d | 3225 | local a, b, c, d |
2665 | local _obj_0 = tb | 3226 | local _obj_0 = tb |
2666 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 3227 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
3228 | Constant = 123 | ||
2667 | local some_string = "Here is a string\n that has a line break in it." | 3229 | local some_string = "Here is a string\n that has a line break in it." |
2668 | print("I am " .. tostring(math.random() * 100) .. "% sure.") | 3230 | print("I am " .. tostring(math.random() * 100) .. "% sure.") |
2669 | local integer = 1000000 | 3231 | local integer = 1000000 |
2670 | local hex = 0xEFBBBF | 3232 | local hex = 0xEFBBBF |
3233 | local binary = 19 | ||
3234 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
3235 | local fn | ||
3236 | fn = function() | ||
3237 | local str = "foo:\n bar: baz" | ||
3238 | return str | ||
3239 | end | ||
3240 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
2671 | local my_function | 3241 | local my_function |
2672 | my_function = function() end | 3242 | my_function = function() end |
2673 | my_function() | 3243 | my_function() |
@@ -2867,11 +3437,10 @@ for i, item in ipairs(items) do | |||
2867 | _len_0 = _len_0 + 1 | 3437 | _len_0 = _len_0 + 1 |
2868 | end | 3438 | end |
2869 | doubled = _accum_0 | 3439 | doubled = _accum_0 |
2870 | local iter = ipairs(items) | ||
2871 | local slice | 3440 | local slice |
2872 | local _accum_0 = { } | 3441 | local _accum_0 = { } |
2873 | local _len_0 = 1 | 3442 | local _len_0 = 1 |
2874 | for i, item in iter do | 3443 | for i, item in ipairs(items) do |
2875 | if i > 1 and i < 3 then | 3444 | if i > 1 and i < 3 then |
2876 | _accum_0[_len_0] = item | 3445 | _accum_0[_len_0] = item |
2877 | _len_0 = _len_0 + 1 | 3446 | _len_0 = _len_0 + 1 |
@@ -2978,8 +3547,7 @@ local slice | |||
2978 | local _accum_0 = { } | 3547 | local _accum_0 = { } |
2979 | local _len_0 = 1 | 3548 | local _len_0 = 1 |
2980 | local _list_0 = items | 3549 | local _list_0 = items |
2981 | local _max_0 = 5 | 3550 | for _index_0 = 1, 5 do |
2982 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
2983 | local item = _list_0[_index_0] | 3551 | local item = _list_0[_index_0] |
2984 | _accum_0[_len_0] = item | 3552 | _accum_0[_len_0] = item |
2985 | _len_0 = _len_0 + 1 | 3553 | _len_0 = _len_0 + 1 |
@@ -2989,7 +3557,8 @@ local slice | |||
2989 | local _accum_0 = { } | 3557 | local _accum_0 = { } |
2990 | local _len_0 = 1 | 3558 | local _len_0 = 1 |
2991 | local _list_0 = items | 3559 | local _list_0 = items |
2992 | for _index_0 = 2, #_list_0 do | 3560 | local _max_0 = #_list_0 |
3561 | for _index_0 = 2, _max_0 do | ||
2993 | local item = _list_0[_index_0] | 3562 | local item = _list_0[_index_0] |
2994 | _accum_0[_len_0] = item | 3563 | _accum_0[_len_0] = item |
2995 | _len_0 = _len_0 + 1 | 3564 | _len_0 = _len_0 + 1 |
@@ -2999,12 +3568,46 @@ local slice | |||
2999 | local _accum_0 = { } | 3568 | local _accum_0 = { } |
3000 | local _len_0 = 1 | 3569 | local _len_0 = 1 |
3001 | local _list_0 = items | 3570 | local _list_0 = items |
3002 | for _index_0 = 1, #_list_0, 2 do | 3571 | local _max_0 = #_list_0 |
3572 | for _index_0 = 1, _max_0, 2 do | ||
3003 | local item = _list_0[_index_0] | 3573 | local item = _list_0[_index_0] |
3004 | _accum_0[_len_0] = item | 3574 | _accum_0[_len_0] = item |
3005 | _len_0 = _len_0 + 1 | 3575 | _len_0 = _len_0 + 1 |
3006 | end | 3576 | end |
3007 | slice = _accum_0 | 3577 | slice = _accum_0 |
3578 | local slice | ||
3579 | local _accum_0 = { } | ||
3580 | local _len_0 = 1 | ||
3581 | local _list_0 = items | ||
3582 | local _min_0 = #_list_0 + -4 + 1 | ||
3583 | local _max_0 = #_list_0 + -1 + 1 | ||
3584 | for _index_0 = _min_0, _max_0 do | ||
3585 | local item = _list_0[_index_0] | ||
3586 | _accum_0[_len_0] = item | ||
3587 | _len_0 = _len_0 + 1 | ||
3588 | end | ||
3589 | slice = _accum_0 | ||
3590 | local reverse_slice | ||
3591 | local _accum_0 = { } | ||
3592 | local _len_0 = 1 | ||
3593 | local _list_0 = items | ||
3594 | local _min_0 = #_list_0 + -1 + 1 | ||
3595 | for _index_0 = _min_0, 1, -1 do | ||
3596 | local item = _list_0[_index_0] | ||
3597 | _accum_0[_len_0] = item | ||
3598 | _len_0 = _len_0 + 1 | ||
3599 | end | ||
3600 | reverse_slice = _accum_0 | ||
3601 | local sub_list | ||
3602 | local _accum_0 = { } | ||
3603 | local _len_0 = 1 | ||
3604 | local _list_0 = items | ||
3605 | for _index_0 = 2, 4 do | ||
3606 | local _item_0 = _list_0[_index_0] | ||
3607 | _accum_0[_len_0] = _item_0 | ||
3608 | _len_0 = _len_0 + 1 | ||
3609 | end | ||
3610 | sub_list = _accum_0 | ||
3008 | for i = 10, 20 do | 3611 | for i = 10, 20 do |
3009 | print(i) | 3612 | print(i) |
3010 | end | 3613 | end |
@@ -3015,8 +3618,7 @@ for key, value in pairs(object) do | |||
3015 | print(key, value) | 3618 | print(key, value) |
3016 | end | 3619 | end |
3017 | local _list_0 = items | 3620 | local _list_0 = items |
3018 | local _max_0 = 4 | 3621 | for _index_0 = 2, 4 do |
3019 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
3020 | local item = _list_0[_index_0] | 3622 | local item = _list_0[_index_0] |
3021 | print(item) | 3623 | print(item) |
3022 | end | 3624 | end |
@@ -3034,12 +3636,24 @@ local _len_0 = 1 | |||
3034 | for i = 1, 20 do | 3636 | for i = 1, 20 do |
3035 | if i % 2 == 0 then | 3637 | if i % 2 == 0 then |
3036 | _accum_0[_len_0] = i * 2 | 3638 | _accum_0[_len_0] = i * 2 |
3639 | _len_0 = _len_0 + 1 | ||
3037 | else | 3640 | else |
3038 | _accum_0[_len_0] = i | 3641 | _accum_0[_len_0] = i |
3642 | _len_0 = _len_0 + 1 | ||
3039 | end | 3643 | end |
3040 | _len_0 = _len_0 + 1 | ||
3041 | end | 3644 | end |
3042 | doubled_evens = _accum_0 | 3645 | doubled_evens = _accum_0 |
3646 | local first_large | ||
3647 | local _accum_0 | ||
3648 | local _list_0 = numbers | ||
3649 | for _index_0 = 1, #_list_0 do | ||
3650 | local n = _list_0[_index_0] | ||
3651 | if n > 10 then | ||
3652 | _accum_0 = n | ||
3653 | break | ||
3654 | end | ||
3655 | end | ||
3656 | first_large = _accum_0 | ||
3043 | local func_a | 3657 | local func_a |
3044 | func_a = function() | 3658 | func_a = function() |
3045 | for i = 1, 10 do | 3659 | for i = 1, 10 do |
@@ -3188,7 +3802,7 @@ if "Robert" == name then | |||
3188 | elseif "Dan" == name or "Daniel" == name then | 3802 | elseif "Dan" == name or "Daniel" == name then |
3189 | print("Your name, it's Dan") | 3803 | print("Your name, it's Dan") |
3190 | else | 3804 | else |
3191 | print("I don't know about your name") | 3805 | print("I don't know about you with name " .. tostring(name)) |
3192 | end | 3806 | end |
3193 | local b = 1 | 3807 | local b = 1 |
3194 | local next_number | 3808 | local next_number |
@@ -3288,6 +3902,192 @@ if _tab_0 then | |||
3288 | end | 3902 | end |
3289 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 3903 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
3290 | end | 3904 | end |
3905 | local _exp_0 = tb | ||
3906 | local _type_0 = type(_exp_0) | ||
3907 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
3908 | local _match_0 = false | ||
3909 | if _tab_0 then | ||
3910 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
3911 | _match_0 = true | ||
3912 | print("1, 2, 3") | ||
3913 | end | ||
3914 | end | ||
3915 | if not _match_0 then | ||
3916 | local _match_1 = false | ||
3917 | if _tab_0 then | ||
3918 | local b = _exp_0[2] | ||
3919 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
3920 | _match_1 = true | ||
3921 | print("1, " .. tostring(b) .. ", 3") | ||
3922 | end | ||
3923 | end | ||
3924 | if not _match_1 then | ||
3925 | if _tab_0 then | ||
3926 | local b = _exp_0[3] | ||
3927 | if b == nil then | ||
3928 | b = 3 | ||
3929 | end | ||
3930 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
3931 | print("1, 2, " .. tostring(b)) | ||
3932 | end | ||
3933 | end | ||
3934 | end | ||
3935 | end | ||
3936 | local _exp_0 = tb | ||
3937 | local _type_0 = type(_exp_0) | ||
3938 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
3939 | local _match_0 = false | ||
3940 | if _tab_0 then | ||
3941 | local result = _exp_0.result | ||
3942 | if true == _exp_0.success and result ~= nil then | ||
3943 | _match_0 = true | ||
3944 | print("success", result) | ||
3945 | end | ||
3946 | end | ||
3947 | if not _match_0 then | ||
3948 | local _match_1 = false | ||
3949 | if _tab_0 then | ||
3950 | if false == _exp_0.success then | ||
3951 | _match_1 = true | ||
3952 | print("failed", result) | ||
3953 | end | ||
3954 | end | ||
3955 | if not _match_1 then | ||
3956 | print("invalid") | ||
3957 | end | ||
3958 | end | ||
3959 | local _exp_0 = tb | ||
3960 | local _type_0 = type(_exp_0) | ||
3961 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
3962 | local _match_0 = false | ||
3963 | if _tab_0 then | ||
3964 | local content | ||
3965 | do | ||
3966 | local _obj_0 = _exp_0.data | ||
3967 | local _type_1 = type(_obj_0) | ||
3968 | if "table" == _type_1 or "userdata" == _type_1 then | ||
3969 | content = _obj_0.content | ||
3970 | end | ||
3971 | end | ||
3972 | local _val_0 | ||
3973 | do | ||
3974 | local _obj_0 = _exp_0.data | ||
3975 | if _obj_0 ~= nil then | ||
3976 | _val_0 = _obj_0.type | ||
3977 | end | ||
3978 | end | ||
3979 | if "success" == _val_0 and content ~= nil then | ||
3980 | _match_0 = true | ||
3981 | print("success", content) | ||
3982 | end | ||
3983 | end | ||
3984 | if not _match_0 then | ||
3985 | local _match_1 = false | ||
3986 | if _tab_0 then | ||
3987 | local content | ||
3988 | do | ||
3989 | local _obj_0 = _exp_0.data | ||
3990 | local _type_1 = type(_obj_0) | ||
3991 | if "table" == _type_1 or "userdata" == _type_1 then | ||
3992 | content = _obj_0.content | ||
3993 | end | ||
3994 | end | ||
3995 | local _val_0 | ||
3996 | do | ||
3997 | local _obj_0 = _exp_0.data | ||
3998 | if _obj_0 ~= nil then | ||
3999 | _val_0 = _obj_0.type | ||
4000 | end | ||
4001 | end | ||
4002 | if "error" == _val_0 and content ~= nil then | ||
4003 | _match_1 = true | ||
4004 | print("failed", content) | ||
4005 | end | ||
4006 | end | ||
4007 | if not _match_1 then | ||
4008 | print("invalid") | ||
4009 | end | ||
4010 | end | ||
4011 | local _exp_0 = tb | ||
4012 | local _type_0 = type(_exp_0) | ||
4013 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4014 | if _tab_0 then | ||
4015 | local fourth = _exp_0[4] | ||
4016 | local _val_0 | ||
4017 | do | ||
4018 | local _obj_0 = _exp_0[1] | ||
4019 | if _obj_0 ~= nil then | ||
4020 | _val_0 = _obj_0.a | ||
4021 | end | ||
4022 | end | ||
4023 | local _val_1 | ||
4024 | do | ||
4025 | local _obj_0 = _exp_0[1] | ||
4026 | if _obj_0 ~= nil then | ||
4027 | _val_1 = _obj_0.b | ||
4028 | end | ||
4029 | end | ||
4030 | local _val_2 | ||
4031 | do | ||
4032 | local _obj_0 = _exp_0[2] | ||
4033 | if _obj_0 ~= nil then | ||
4034 | _val_2 = _obj_0.a | ||
4035 | end | ||
4036 | end | ||
4037 | local _val_3 | ||
4038 | do | ||
4039 | local _obj_0 = _exp_0[2] | ||
4040 | if _obj_0 ~= nil then | ||
4041 | _val_3 = _obj_0.b | ||
4042 | end | ||
4043 | end | ||
4044 | local _val_4 | ||
4045 | do | ||
4046 | local _obj_0 = _exp_0[3] | ||
4047 | if _obj_0 ~= nil then | ||
4048 | _val_4 = _obj_0.a | ||
4049 | end | ||
4050 | end | ||
4051 | local _val_5 | ||
4052 | do | ||
4053 | local _obj_0 = _exp_0[3] | ||
4054 | if _obj_0 ~= nil then | ||
4055 | _val_5 = _obj_0.b | ||
4056 | end | ||
4057 | end | ||
4058 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
4059 | print("matched", fourth) | ||
4060 | end | ||
4061 | end | ||
4062 | local segments = { | ||
4063 | "admin", | ||
4064 | "users", | ||
4065 | "logs", | ||
4066 | "view" | ||
4067 | } | ||
4068 | local _type_0 = type(segments) | ||
4069 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4070 | if _tab_0 then | ||
4071 | local groups | ||
4072 | do | ||
4073 | local _accum_0 = { } | ||
4074 | local _len_0 = 1 | ||
4075 | local _max_0 = #segments + -3 + 1 | ||
4076 | for _index_0 = 1, _max_0 do | ||
4077 | local _item_0 = segments[_index_0] | ||
4078 | _accum_0[_len_0] = _item_0 | ||
4079 | _len_0 = _len_0 + 1 | ||
4080 | end | ||
4081 | groups = _accum_0 | ||
4082 | end | ||
4083 | local resource = segments[#segments - 1] | ||
4084 | local action = segments[#segments] | ||
4085 | if resource ~= nil and action ~= nil then | ||
4086 | print("Group:", groups) | ||
4087 | print("Resource:", resource) | ||
4088 | print("Action:", action) | ||
4089 | end | ||
4090 | end | ||
3291 | local Inventory | 4091 | local Inventory |
3292 | local _class_0 | 4092 | local _class_0 |
3293 | local _base_0 = { | 4093 | local _base_0 = { |
@@ -3944,6 +4744,10 @@ do | |||
3944 | _with_1["key-name"] = value | 4744 | _with_1["key-name"] = value |
3945 | end | 4745 | end |
3946 | _with_0[#_with_0 + 1] = "abc" | 4746 | _with_0[#_with_0 + 1] = "abc" |
4747 | local _with_0 = obj | ||
4748 | if _with_0 ~= nil then | ||
4749 | print(obj.name) | ||
4750 | end | ||
3947 | do | 4751 | do |
3948 | local var = "hello" | 4752 | local var = "hello" |
3949 | print(var) | 4753 | print(var) |
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index ffa0483..b54d6d7 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua | |||
@@ -20,6 +20,38 @@ local inventory = { | |||
20 | } | 20 | } |
21 | } | 21 | } |
22 | } | 22 | } |
23 | local map | ||
24 | map = function(arr, action) | ||
25 | local _accum_0 = { } | ||
26 | local _len_0 = 1 | ||
27 | for _index_0 = 1, #arr do | ||
28 | local item = arr[_index_0] | ||
29 | _accum_0[_len_0] = action(item) | ||
30 | _len_0 = _len_0 + 1 | ||
31 | end | ||
32 | return _accum_0 | ||
33 | end | ||
34 | local filter | ||
35 | filter = function(arr, cond) | ||
36 | local _accum_0 = { } | ||
37 | local _len_0 = 1 | ||
38 | for _index_0 = 1, #arr do | ||
39 | local item = arr[_index_0] | ||
40 | if cond(item) then | ||
41 | _accum_0[_len_0] = item | ||
42 | _len_0 = _len_0 + 1 | ||
43 | end | ||
44 | end | ||
45 | return _accum_0 | ||
46 | end | ||
47 | local reduce | ||
48 | reduce = function(arr, init, action) | ||
49 | for _index_0 = 1, #arr do | ||
50 | local item = arr[_index_0] | ||
51 | init = action(init, item) | ||
52 | end | ||
53 | return init | ||
54 | end | ||
23 | print(reduce(filter(map({ | 55 | print(reduce(filter(map({ |
24 | 1, | 56 | 1, |
25 | 2, | 57 | 2, |
@@ -77,6 +109,12 @@ end | |||
77 | print("yuescript") | 109 | print("yuescript") |
78 | print(3) | 110 | print(3) |
79 | print("ζζηζδΈΎη±»ε:", "Static") | 111 | print("ζζηζδΈΎη±»ε:", "Static") |
112 | do | ||
113 | print(123, "hello") | ||
114 | end | ||
115 | do | ||
116 | print(123, "hello") | ||
117 | end | ||
80 | if tb ~= nil then | 118 | if tb ~= nil then |
81 | tb:func() | 119 | tb:func() |
82 | end | 120 | end |
@@ -177,6 +215,16 @@ for _key_0, _value_0 in pairs(b) do | |||
177 | end | 215 | end |
178 | end | 216 | end |
179 | merge = _tab_0 | 217 | merge = _tab_0 |
218 | local last | ||
219 | do | ||
220 | local _item_0 = data.items | ||
221 | last = _item_0[#_item_0] | ||
222 | end | ||
223 | local second_last | ||
224 | do | ||
225 | local _item_0 = data.items | ||
226 | second_last = _item_0[#_item_0 - 1] | ||
227 | end | ||
180 | local mt = { } | 228 | local mt = { } |
181 | local add | 229 | local add |
182 | add = function(self, right) | 230 | add = function(self, right) |
@@ -307,6 +355,14 @@ func({ | |||
307 | 2, | 355 | 2, |
308 | 3 | 356 | 3 |
309 | }) | 357 | }) |
358 | local f | ||
359 | f = function() | ||
360 | return { | ||
361 | 1, | ||
362 | 2, | ||
363 | 3 | ||
364 | } | ||
365 | end | ||
310 | local tb = { | 366 | local tb = { |
311 | name = "abc", | 367 | name = "abc", |
312 | values = { | 368 | values = { |
@@ -547,6 +603,59 @@ end | |||
547 | local two, four | 603 | local two, four |
548 | local _obj_0 = items | 604 | local _obj_0 = items |
549 | two, four = _obj_0[2], _obj_0[4] | 605 | two, four = _obj_0[2], _obj_0[4] |
606 | local orders = { | ||
607 | "first", | ||
608 | "second", | ||
609 | "third", | ||
610 | "fourth", | ||
611 | "last" | ||
612 | } | ||
613 | local first, bulk, last = orders[1], (function() | ||
614 | local _accum_0 = { } | ||
615 | local _len_0 = 1 | ||
616 | local _max_0 = #orders + -2 + 1 | ||
617 | for _index_0 = 2, _max_0 do | ||
618 | local _item_0 = orders[_index_0] | ||
619 | _accum_0[_len_0] = _item_0 | ||
620 | _len_0 = _len_0 + 1 | ||
621 | end | ||
622 | return _accum_0 | ||
623 | end)(), orders[#orders] | ||
624 | print(first) | ||
625 | print(bulk) | ||
626 | print(last) | ||
627 | local first, rest | ||
628 | do | ||
629 | local _obj_0 = orders | ||
630 | first, rest = _obj_0[1], (function() | ||
631 | local _accum_0 = { } | ||
632 | local _len_0 = 1 | ||
633 | local _max_0 = #_obj_0 | ||
634 | for _index_0 = 2, _max_0 do | ||
635 | local _item_0 = _obj_0[_index_0] | ||
636 | _accum_0[_len_0] = _item_0 | ||
637 | _len_0 = _len_0 + 1 | ||
638 | end | ||
639 | return _accum_0 | ||
640 | end)() | ||
641 | end | ||
642 | local start, last | ||
643 | do | ||
644 | local _obj_0 = orders | ||
645 | start, last = (function() | ||
646 | local _accum_0 = { } | ||
647 | local _len_0 = 1 | ||
648 | local _max_0 = #_obj_0 + -2 + 1 | ||
649 | for _index_0 = 1, _max_0 do | ||
650 | local _item_0 = _obj_0[_index_0] | ||
651 | _accum_0[_len_0] = _item_0 | ||
652 | _len_0 = _len_0 + 1 | ||
653 | end | ||
654 | return _accum_0 | ||
655 | end)(), _obj_0[#_obj_0] | ||
656 | end | ||
657 | local _obj_0 = orders | ||
658 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
550 | local tuples = { | 659 | local tuples = { |
551 | { | 660 | { |
552 | "hello", | 661 | "hello", |
@@ -648,6 +757,56 @@ end) | |||
648 | if success then | 757 | if success then |
649 | print(result) | 758 | print(result) |
650 | end | 759 | end |
760 | local a, b, c | ||
761 | do | ||
762 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
763 | return func() | ||
764 | end) | ||
765 | if _ok_0 then | ||
766 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
767 | end | ||
768 | end | ||
769 | do | ||
770 | local _exp_0 = ((function() | ||
771 | return (function(_arg_0, ...) | ||
772 | local _ok_0 = _arg_0 | ||
773 | if _ok_0 then | ||
774 | return ... | ||
775 | end | ||
776 | end)(pcall(function() | ||
777 | return func() | ||
778 | end)) | ||
779 | end)()) | ||
780 | if _exp_0 ~= nil then | ||
781 | a = _exp_0 | ||
782 | else | ||
783 | a = "default" | ||
784 | end | ||
785 | end | ||
786 | f((function() | ||
787 | return (function(_arg_0, ...) | ||
788 | local _ok_0 = _arg_0 | ||
789 | if _ok_0 then | ||
790 | return ... | ||
791 | end | ||
792 | end)(pcall(function() | ||
793 | return func() | ||
794 | end)) | ||
795 | end)()) | ||
796 | f((function() | ||
797 | return (function(_arg_0, ...) | ||
798 | local _ok_0 = _arg_0 | ||
799 | if _ok_0 then | ||
800 | return ... | ||
801 | end | ||
802 | end)(xpcall(function() | ||
803 | print(123) | ||
804 | return func() | ||
805 | end, function(e) | ||
806 | print(e) | ||
807 | return e | ||
808 | end)) | ||
809 | end)()) | ||
651 | local a <const> = 123 | 810 | local a <const> = 123 |
652 | local _ <close> = setmetatable({ }, { | 811 | local _ <close> = setmetatable({ }, { |
653 | __close = function() | 812 | __close = function() |
@@ -657,10 +816,19 @@ local _ <close> = setmetatable({ }, { | |||
657 | local a, b, c, d | 816 | local a, b, c, d |
658 | local _obj_0 = tb | 817 | local _obj_0 = tb |
659 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 818 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
819 | Constant = 123 | ||
660 | local some_string = "θΏζ―δΈδΈͺε符串\n εΉΆε ζ¬δΈδΈͺζ’θ‘γ" | 820 | local some_string = "θΏζ―δΈδΈͺε符串\n εΉΆε ζ¬δΈδΈͺζ’θ‘γ" |
661 | print("ζζ" .. tostring(math.random() * 100) .. "%ηζζ‘γ") | 821 | print("ζζ" .. tostring(math.random() * 100) .. "%ηζζ‘γ") |
662 | local integer = 1000000 | 822 | local integer = 1000000 |
663 | local hex = 0xEFBBBF | 823 | local hex = 0xEFBBBF |
824 | local binary = 19 | ||
825 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
826 | local fn | ||
827 | fn = function() | ||
828 | local str = "foo:\n bar: baz" | ||
829 | return str | ||
830 | end | ||
831 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
664 | local my_function | 832 | local my_function |
665 | my_function = function() end | 833 | my_function = function() end |
666 | my_function() | 834 | my_function() |
@@ -854,11 +1022,10 @@ for i, item in ipairs(items) do | |||
854 | _len_0 = _len_0 + 1 | 1022 | _len_0 = _len_0 + 1 |
855 | end | 1023 | end |
856 | doubled = _accum_0 | 1024 | doubled = _accum_0 |
857 | local iter = ipairs(items) | ||
858 | local slice | 1025 | local slice |
859 | local _accum_0 = { } | 1026 | local _accum_0 = { } |
860 | local _len_0 = 1 | 1027 | local _len_0 = 1 |
861 | for i, item in iter do | 1028 | for i, item in ipairs(items) do |
862 | if i > 1 and i < 3 then | 1029 | if i > 1 and i < 3 then |
863 | _accum_0[_len_0] = item | 1030 | _accum_0[_len_0] = item |
864 | _len_0 = _len_0 + 1 | 1031 | _len_0 = _len_0 + 1 |
@@ -965,8 +1132,7 @@ local slice | |||
965 | local _accum_0 = { } | 1132 | local _accum_0 = { } |
966 | local _len_0 = 1 | 1133 | local _len_0 = 1 |
967 | local _list_0 = items | 1134 | local _list_0 = items |
968 | local _max_0 = 5 | 1135 | for _index_0 = 1, 5 do |
969 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
970 | local item = _list_0[_index_0] | 1136 | local item = _list_0[_index_0] |
971 | _accum_0[_len_0] = item | 1137 | _accum_0[_len_0] = item |
972 | _len_0 = _len_0 + 1 | 1138 | _len_0 = _len_0 + 1 |
@@ -976,7 +1142,8 @@ local slice | |||
976 | local _accum_0 = { } | 1142 | local _accum_0 = { } |
977 | local _len_0 = 1 | 1143 | local _len_0 = 1 |
978 | local _list_0 = items | 1144 | local _list_0 = items |
979 | for _index_0 = 2, #_list_0 do | 1145 | local _max_0 = #_list_0 |
1146 | for _index_0 = 2, _max_0 do | ||
980 | local item = _list_0[_index_0] | 1147 | local item = _list_0[_index_0] |
981 | _accum_0[_len_0] = item | 1148 | _accum_0[_len_0] = item |
982 | _len_0 = _len_0 + 1 | 1149 | _len_0 = _len_0 + 1 |
@@ -986,12 +1153,46 @@ local slice | |||
986 | local _accum_0 = { } | 1153 | local _accum_0 = { } |
987 | local _len_0 = 1 | 1154 | local _len_0 = 1 |
988 | local _list_0 = items | 1155 | local _list_0 = items |
989 | for _index_0 = 1, #_list_0, 2 do | 1156 | local _max_0 = #_list_0 |
1157 | for _index_0 = 1, _max_0, 2 do | ||
990 | local item = _list_0[_index_0] | 1158 | local item = _list_0[_index_0] |
991 | _accum_0[_len_0] = item | 1159 | _accum_0[_len_0] = item |
992 | _len_0 = _len_0 + 1 | 1160 | _len_0 = _len_0 + 1 |
993 | end | 1161 | end |
994 | slice = _accum_0 | 1162 | slice = _accum_0 |
1163 | local slice | ||
1164 | local _accum_0 = { } | ||
1165 | local _len_0 = 1 | ||
1166 | local _list_0 = items | ||
1167 | local _min_0 = #_list_0 + -4 + 1 | ||
1168 | local _max_0 = #_list_0 + -1 + 1 | ||
1169 | for _index_0 = _min_0, _max_0 do | ||
1170 | local item = _list_0[_index_0] | ||
1171 | _accum_0[_len_0] = item | ||
1172 | _len_0 = _len_0 + 1 | ||
1173 | end | ||
1174 | slice = _accum_0 | ||
1175 | local reverse_slice | ||
1176 | local _accum_0 = { } | ||
1177 | local _len_0 = 1 | ||
1178 | local _list_0 = items | ||
1179 | local _min_0 = #_list_0 + -1 + 1 | ||
1180 | for _index_0 = _min_0, 1, -1 do | ||
1181 | local item = _list_0[_index_0] | ||
1182 | _accum_0[_len_0] = item | ||
1183 | _len_0 = _len_0 + 1 | ||
1184 | end | ||
1185 | reverse_slice = _accum_0 | ||
1186 | local sub_list | ||
1187 | local _accum_0 = { } | ||
1188 | local _len_0 = 1 | ||
1189 | local _list_0 = items | ||
1190 | for _index_0 = 2, 4 do | ||
1191 | local _item_0 = _list_0[_index_0] | ||
1192 | _accum_0[_len_0] = _item_0 | ||
1193 | _len_0 = _len_0 + 1 | ||
1194 | end | ||
1195 | sub_list = _accum_0 | ||
995 | for i = 10, 20 do | 1196 | for i = 10, 20 do |
996 | print(i) | 1197 | print(i) |
997 | end | 1198 | end |
@@ -1002,8 +1203,7 @@ for key, value in pairs(object) do | |||
1002 | print(key, value) | 1203 | print(key, value) |
1003 | end | 1204 | end |
1004 | local _list_0 = items | 1205 | local _list_0 = items |
1005 | local _max_0 = 4 | 1206 | for _index_0 = 2, 4 do |
1006 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
1007 | local item = _list_0[_index_0] | 1207 | local item = _list_0[_index_0] |
1008 | print(item) | 1208 | print(item) |
1009 | end | 1209 | end |
@@ -1021,12 +1221,24 @@ local _len_0 = 1 | |||
1021 | for i = 1, 20 do | 1221 | for i = 1, 20 do |
1022 | if i % 2 == 0 then | 1222 | if i % 2 == 0 then |
1023 | _accum_0[_len_0] = i * 2 | 1223 | _accum_0[_len_0] = i * 2 |
1224 | _len_0 = _len_0 + 1 | ||
1024 | else | 1225 | else |
1025 | _accum_0[_len_0] = i | 1226 | _accum_0[_len_0] = i |
1227 | _len_0 = _len_0 + 1 | ||
1026 | end | 1228 | end |
1027 | _len_0 = _len_0 + 1 | ||
1028 | end | 1229 | end |
1029 | doubled_evens = _accum_0 | 1230 | doubled_evens = _accum_0 |
1231 | local first_large | ||
1232 | local _accum_0 | ||
1233 | local _list_0 = numbers | ||
1234 | for _index_0 = 1, #_list_0 do | ||
1235 | local n = _list_0[_index_0] | ||
1236 | if n > 10 then | ||
1237 | _accum_0 = n | ||
1238 | break | ||
1239 | end | ||
1240 | end | ||
1241 | first_large = _accum_0 | ||
1030 | local func_a | 1242 | local func_a |
1031 | func_a = function() | 1243 | func_a = function() |
1032 | for i = 1, 10 do | 1244 | for i = 1, 10 do |
@@ -1175,7 +1387,7 @@ if "Robert" == name then | |||
1175 | elseif "Dan" == name or "Daniel" == name then | 1387 | elseif "Dan" == name or "Daniel" == name then |
1176 | print("δ½ ηεεζ―Dan") | 1388 | print("δ½ ηεεζ―Dan") |
1177 | else | 1389 | else |
1178 | print("ζδΈη₯ιδ½ ηεε") | 1390 | print("ζδΈθ€θ―δ½ οΌδ½ ηεεζ―" .. tostring(name)) |
1179 | end | 1391 | end |
1180 | local b = 1 | 1392 | local b = 1 |
1181 | local next_number | 1393 | local next_number |
@@ -1275,6 +1487,192 @@ if _tab_0 then | |||
1275 | end | 1487 | end |
1276 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 1488 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
1277 | end | 1489 | end |
1490 | local _exp_0 = tb | ||
1491 | local _type_0 = type(_exp_0) | ||
1492 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1493 | local _match_0 = false | ||
1494 | if _tab_0 then | ||
1495 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
1496 | _match_0 = true | ||
1497 | print("1, 2, 3") | ||
1498 | end | ||
1499 | end | ||
1500 | if not _match_0 then | ||
1501 | local _match_1 = false | ||
1502 | if _tab_0 then | ||
1503 | local b = _exp_0[2] | ||
1504 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
1505 | _match_1 = true | ||
1506 | print("1, " .. tostring(b) .. ", 3") | ||
1507 | end | ||
1508 | end | ||
1509 | if not _match_1 then | ||
1510 | if _tab_0 then | ||
1511 | local b = _exp_0[3] | ||
1512 | if b == nil then | ||
1513 | b = 3 | ||
1514 | end | ||
1515 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
1516 | print("1, 2, " .. tostring(b)) | ||
1517 | end | ||
1518 | end | ||
1519 | end | ||
1520 | end | ||
1521 | local _exp_0 = tb | ||
1522 | local _type_0 = type(_exp_0) | ||
1523 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1524 | local _match_0 = false | ||
1525 | if _tab_0 then | ||
1526 | local result = _exp_0.result | ||
1527 | if true == _exp_0.success and result ~= nil then | ||
1528 | _match_0 = true | ||
1529 | print("ζε", result) | ||
1530 | end | ||
1531 | end | ||
1532 | if not _match_0 then | ||
1533 | local _match_1 = false | ||
1534 | if _tab_0 then | ||
1535 | if false == _exp_0.success then | ||
1536 | _match_1 = true | ||
1537 | print("ε€±θ΄₯", result) | ||
1538 | end | ||
1539 | end | ||
1540 | if not _match_1 then | ||
1541 | print("ζ ζεΌ") | ||
1542 | end | ||
1543 | end | ||
1544 | local _exp_0 = tb | ||
1545 | local _type_0 = type(_exp_0) | ||
1546 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1547 | local _match_0 = false | ||
1548 | if _tab_0 then | ||
1549 | local content | ||
1550 | do | ||
1551 | local _obj_0 = _exp_0.data | ||
1552 | local _type_1 = type(_obj_0) | ||
1553 | if "table" == _type_1 or "userdata" == _type_1 then | ||
1554 | content = _obj_0.content | ||
1555 | end | ||
1556 | end | ||
1557 | local _val_0 | ||
1558 | do | ||
1559 | local _obj_0 = _exp_0.data | ||
1560 | if _obj_0 ~= nil then | ||
1561 | _val_0 = _obj_0.type | ||
1562 | end | ||
1563 | end | ||
1564 | if "success" == _val_0 and content ~= nil then | ||
1565 | _match_0 = true | ||
1566 | print("ζε", content) | ||
1567 | end | ||
1568 | end | ||
1569 | if not _match_0 then | ||
1570 | local _match_1 = false | ||
1571 | if _tab_0 then | ||
1572 | local content | ||
1573 | do | ||
1574 | local _obj_0 = _exp_0.data | ||
1575 | local _type_1 = type(_obj_0) | ||
1576 | if "table" == _type_1 or "userdata" == _type_1 then | ||
1577 | content = _obj_0.content | ||
1578 | end | ||
1579 | end | ||
1580 | local _val_0 | ||
1581 | do | ||
1582 | local _obj_0 = _exp_0.data | ||
1583 | if _obj_0 ~= nil then | ||
1584 | _val_0 = _obj_0.type | ||
1585 | end | ||
1586 | end | ||
1587 | if "error" == _val_0 and content ~= nil then | ||
1588 | _match_1 = true | ||
1589 | print("ε€±θ΄₯", content) | ||
1590 | end | ||
1591 | end | ||
1592 | if not _match_1 then | ||
1593 | print("ζ ζεΌ") | ||
1594 | end | ||
1595 | end | ||
1596 | local _exp_0 = tb | ||
1597 | local _type_0 = type(_exp_0) | ||
1598 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1599 | if _tab_0 then | ||
1600 | local fourth = _exp_0[4] | ||
1601 | local _val_0 | ||
1602 | do | ||
1603 | local _obj_0 = _exp_0[1] | ||
1604 | if _obj_0 ~= nil then | ||
1605 | _val_0 = _obj_0.a | ||
1606 | end | ||
1607 | end | ||
1608 | local _val_1 | ||
1609 | do | ||
1610 | local _obj_0 = _exp_0[1] | ||
1611 | if _obj_0 ~= nil then | ||
1612 | _val_1 = _obj_0.b | ||
1613 | end | ||
1614 | end | ||
1615 | local _val_2 | ||
1616 | do | ||
1617 | local _obj_0 = _exp_0[2] | ||
1618 | if _obj_0 ~= nil then | ||
1619 | _val_2 = _obj_0.a | ||
1620 | end | ||
1621 | end | ||
1622 | local _val_3 | ||
1623 | do | ||
1624 | local _obj_0 = _exp_0[2] | ||
1625 | if _obj_0 ~= nil then | ||
1626 | _val_3 = _obj_0.b | ||
1627 | end | ||
1628 | end | ||
1629 | local _val_4 | ||
1630 | do | ||
1631 | local _obj_0 = _exp_0[3] | ||
1632 | if _obj_0 ~= nil then | ||
1633 | _val_4 = _obj_0.a | ||
1634 | end | ||
1635 | end | ||
1636 | local _val_5 | ||
1637 | do | ||
1638 | local _obj_0 = _exp_0[3] | ||
1639 | if _obj_0 ~= nil then | ||
1640 | _val_5 = _obj_0.b | ||
1641 | end | ||
1642 | end | ||
1643 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
1644 | print("εΉι ζε", fourth) | ||
1645 | end | ||
1646 | end | ||
1647 | local segments = { | ||
1648 | "admin", | ||
1649 | "users", | ||
1650 | "logs", | ||
1651 | "view" | ||
1652 | } | ||
1653 | local _type_0 = type(segments) | ||
1654 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1655 | if _tab_0 then | ||
1656 | local groups | ||
1657 | do | ||
1658 | local _accum_0 = { } | ||
1659 | local _len_0 = 1 | ||
1660 | local _max_0 = #segments + -3 + 1 | ||
1661 | for _index_0 = 1, _max_0 do | ||
1662 | local _item_0 = segments[_index_0] | ||
1663 | _accum_0[_len_0] = _item_0 | ||
1664 | _len_0 = _len_0 + 1 | ||
1665 | end | ||
1666 | groups = _accum_0 | ||
1667 | end | ||
1668 | local resource = segments[#segments - 1] | ||
1669 | local action = segments[#segments] | ||
1670 | if resource ~= nil and action ~= nil then | ||
1671 | print("Group:", groups) | ||
1672 | print("Resource:", resource) | ||
1673 | print("Action:", action) | ||
1674 | end | ||
1675 | end | ||
1278 | local Inventory | 1676 | local Inventory |
1279 | local _class_0 | 1677 | local _class_0 |
1280 | local _base_0 = { | 1678 | local _base_0 = { |
@@ -1931,6 +2329,10 @@ do | |||
1931 | _with_1["key-name"] = value | 2329 | _with_1["key-name"] = value |
1932 | end | 2330 | end |
1933 | _with_0[#_with_0 + 1] = "abc" | 2331 | _with_0[#_with_0 + 1] = "abc" |
2332 | local _with_0 = obj | ||
2333 | if _with_0 ~= nil then | ||
2334 | print(obj.name) | ||
2335 | end | ||
1934 | do | 2336 | do |
1935 | local var = "hello" | 2337 | local var = "hello" |
1936 | print(var) | 2338 | print(var) |
@@ -2021,6 +2423,38 @@ local inventory = { | |||
2021 | } | 2423 | } |
2022 | } | 2424 | } |
2023 | } | 2425 | } |
2426 | local map | ||
2427 | map = function(arr, action) | ||
2428 | local _accum_0 = { } | ||
2429 | local _len_0 = 1 | ||
2430 | for _index_0 = 1, #arr do | ||
2431 | local item = arr[_index_0] | ||
2432 | _accum_0[_len_0] = action(item) | ||
2433 | _len_0 = _len_0 + 1 | ||
2434 | end | ||
2435 | return _accum_0 | ||
2436 | end | ||
2437 | local filter | ||
2438 | filter = function(arr, cond) | ||
2439 | local _accum_0 = { } | ||
2440 | local _len_0 = 1 | ||
2441 | for _index_0 = 1, #arr do | ||
2442 | local item = arr[_index_0] | ||
2443 | if cond(item) then | ||
2444 | _accum_0[_len_0] = item | ||
2445 | _len_0 = _len_0 + 1 | ||
2446 | end | ||
2447 | end | ||
2448 | return _accum_0 | ||
2449 | end | ||
2450 | local reduce | ||
2451 | reduce = function(arr, init, action) | ||
2452 | for _index_0 = 1, #arr do | ||
2453 | local item = arr[_index_0] | ||
2454 | init = action(init, item) | ||
2455 | end | ||
2456 | return init | ||
2457 | end | ||
2024 | print(reduce(filter(map({ | 2458 | print(reduce(filter(map({ |
2025 | 1, | 2459 | 1, |
2026 | 2, | 2460 | 2, |
@@ -2078,6 +2512,12 @@ end | |||
2078 | print("yuescript") | 2512 | print("yuescript") |
2079 | print(3) | 2513 | print(3) |
2080 | print("ζζηζδΈΎη±»ε:", "Static") | 2514 | print("ζζηζδΈΎη±»ε:", "Static") |
2515 | do | ||
2516 | print(123, "hello") | ||
2517 | end | ||
2518 | do | ||
2519 | print(123, "hello") | ||
2520 | end | ||
2081 | if tb ~= nil then | 2521 | if tb ~= nil then |
2082 | tb:func() | 2522 | tb:func() |
2083 | end | 2523 | end |
@@ -2178,6 +2618,16 @@ for _key_0, _value_0 in pairs(b) do | |||
2178 | end | 2618 | end |
2179 | end | 2619 | end |
2180 | merge = _tab_0 | 2620 | merge = _tab_0 |
2621 | local last | ||
2622 | do | ||
2623 | local _item_0 = data.items | ||
2624 | last = _item_0[#_item_0] | ||
2625 | end | ||
2626 | local second_last | ||
2627 | do | ||
2628 | local _item_0 = data.items | ||
2629 | second_last = _item_0[#_item_0 - 1] | ||
2630 | end | ||
2181 | local mt = { } | 2631 | local mt = { } |
2182 | local add | 2632 | local add |
2183 | add = function(self, right) | 2633 | add = function(self, right) |
@@ -2308,6 +2758,14 @@ func({ | |||
2308 | 2, | 2758 | 2, |
2309 | 3 | 2759 | 3 |
2310 | }) | 2760 | }) |
2761 | local f | ||
2762 | f = function() | ||
2763 | return { | ||
2764 | 1, | ||
2765 | 2, | ||
2766 | 3 | ||
2767 | } | ||
2768 | end | ||
2311 | local tb = { | 2769 | local tb = { |
2312 | name = "abc", | 2770 | name = "abc", |
2313 | values = { | 2771 | values = { |
@@ -2548,6 +3006,59 @@ end | |||
2548 | local two, four | 3006 | local two, four |
2549 | local _obj_0 = items | 3007 | local _obj_0 = items |
2550 | two, four = _obj_0[2], _obj_0[4] | 3008 | two, four = _obj_0[2], _obj_0[4] |
3009 | local orders = { | ||
3010 | "first", | ||
3011 | "second", | ||
3012 | "third", | ||
3013 | "fourth", | ||
3014 | "last" | ||
3015 | } | ||
3016 | local first, bulk, last = orders[1], (function() | ||
3017 | local _accum_0 = { } | ||
3018 | local _len_0 = 1 | ||
3019 | local _max_0 = #orders + -2 + 1 | ||
3020 | for _index_0 = 2, _max_0 do | ||
3021 | local _item_0 = orders[_index_0] | ||
3022 | _accum_0[_len_0] = _item_0 | ||
3023 | _len_0 = _len_0 + 1 | ||
3024 | end | ||
3025 | return _accum_0 | ||
3026 | end)(), orders[#orders] | ||
3027 | print(first) | ||
3028 | print(bulk) | ||
3029 | print(last) | ||
3030 | local first, rest | ||
3031 | do | ||
3032 | local _obj_0 = orders | ||
3033 | first, rest = _obj_0[1], (function() | ||
3034 | local _accum_0 = { } | ||
3035 | local _len_0 = 1 | ||
3036 | local _max_0 = #_obj_0 | ||
3037 | for _index_0 = 2, _max_0 do | ||
3038 | local _item_0 = _obj_0[_index_0] | ||
3039 | _accum_0[_len_0] = _item_0 | ||
3040 | _len_0 = _len_0 + 1 | ||
3041 | end | ||
3042 | return _accum_0 | ||
3043 | end)() | ||
3044 | end | ||
3045 | local start, last | ||
3046 | do | ||
3047 | local _obj_0 = orders | ||
3048 | start, last = (function() | ||
3049 | local _accum_0 = { } | ||
3050 | local _len_0 = 1 | ||
3051 | local _max_0 = #_obj_0 + -2 + 1 | ||
3052 | for _index_0 = 1, _max_0 do | ||
3053 | local _item_0 = _obj_0[_index_0] | ||
3054 | _accum_0[_len_0] = _item_0 | ||
3055 | _len_0 = _len_0 + 1 | ||
3056 | end | ||
3057 | return _accum_0 | ||
3058 | end)(), _obj_0[#_obj_0] | ||
3059 | end | ||
3060 | local _obj_0 = orders | ||
3061 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
2551 | local tuples = { | 3062 | local tuples = { |
2552 | { | 3063 | { |
2553 | "hello", | 3064 | "hello", |
@@ -2649,6 +3160,56 @@ end) | |||
2649 | if success then | 3160 | if success then |
2650 | print(result) | 3161 | print(result) |
2651 | end | 3162 | end |
3163 | local a, b, c | ||
3164 | do | ||
3165 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
3166 | return func() | ||
3167 | end) | ||
3168 | if _ok_0 then | ||
3169 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
3170 | end | ||
3171 | end | ||
3172 | do | ||
3173 | local _exp_0 = ((function() | ||
3174 | return (function(_arg_0, ...) | ||
3175 | local _ok_0 = _arg_0 | ||
3176 | if _ok_0 then | ||
3177 | return ... | ||
3178 | end | ||
3179 | end)(pcall(function() | ||
3180 | return func() | ||
3181 | end)) | ||
3182 | end)()) | ||
3183 | if _exp_0 ~= nil then | ||
3184 | a = _exp_0 | ||
3185 | else | ||
3186 | a = "default" | ||
3187 | end | ||
3188 | end | ||
3189 | f((function() | ||
3190 | return (function(_arg_0, ...) | ||
3191 | local _ok_0 = _arg_0 | ||
3192 | if _ok_0 then | ||
3193 | return ... | ||
3194 | end | ||
3195 | end)(pcall(function() | ||
3196 | return func() | ||
3197 | end)) | ||
3198 | end)()) | ||
3199 | f((function() | ||
3200 | return (function(_arg_0, ...) | ||
3201 | local _ok_0 = _arg_0 | ||
3202 | if _ok_0 then | ||
3203 | return ... | ||
3204 | end | ||
3205 | end)(xpcall(function() | ||
3206 | print(123) | ||
3207 | return func() | ||
3208 | end, function(e) | ||
3209 | print(e) | ||
3210 | return e | ||
3211 | end)) | ||
3212 | end)()) | ||
2652 | local a <const> = 123 | 3213 | local a <const> = 123 |
2653 | local _ <close> = setmetatable({ }, { | 3214 | local _ <close> = setmetatable({ }, { |
2654 | __close = function() | 3215 | __close = function() |
@@ -2658,10 +3219,19 @@ local _ <close> = setmetatable({ }, { | |||
2658 | local a, b, c, d | 3219 | local a, b, c, d |
2659 | local _obj_0 = tb | 3220 | local _obj_0 = tb |
2660 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 3221 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
3222 | Constant = 123 | ||
2661 | local some_string = "θΏζ―δΈδΈͺε符串\n εΉΆε ζ¬δΈδΈͺζ’θ‘γ" | 3223 | local some_string = "θΏζ―δΈδΈͺε符串\n εΉΆε ζ¬δΈδΈͺζ’θ‘γ" |
2662 | print("ζζ" .. tostring(math.random() * 100) .. "%ηζζ‘γ") | 3224 | print("ζζ" .. tostring(math.random() * 100) .. "%ηζζ‘γ") |
2663 | local integer = 1000000 | 3225 | local integer = 1000000 |
2664 | local hex = 0xEFBBBF | 3226 | local hex = 0xEFBBBF |
3227 | local binary = 19 | ||
3228 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
3229 | local fn | ||
3230 | fn = function() | ||
3231 | local str = "foo:\n bar: baz" | ||
3232 | return str | ||
3233 | end | ||
3234 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
2665 | local my_function | 3235 | local my_function |
2666 | my_function = function() end | 3236 | my_function = function() end |
2667 | my_function() | 3237 | my_function() |
@@ -2855,11 +3425,10 @@ for i, item in ipairs(items) do | |||
2855 | _len_0 = _len_0 + 1 | 3425 | _len_0 = _len_0 + 1 |
2856 | end | 3426 | end |
2857 | doubled = _accum_0 | 3427 | doubled = _accum_0 |
2858 | local iter = ipairs(items) | ||
2859 | local slice | 3428 | local slice |
2860 | local _accum_0 = { } | 3429 | local _accum_0 = { } |
2861 | local _len_0 = 1 | 3430 | local _len_0 = 1 |
2862 | for i, item in iter do | 3431 | for i, item in ipairs(items) do |
2863 | if i > 1 and i < 3 then | 3432 | if i > 1 and i < 3 then |
2864 | _accum_0[_len_0] = item | 3433 | _accum_0[_len_0] = item |
2865 | _len_0 = _len_0 + 1 | 3434 | _len_0 = _len_0 + 1 |
@@ -2966,8 +3535,7 @@ local slice | |||
2966 | local _accum_0 = { } | 3535 | local _accum_0 = { } |
2967 | local _len_0 = 1 | 3536 | local _len_0 = 1 |
2968 | local _list_0 = items | 3537 | local _list_0 = items |
2969 | local _max_0 = 5 | 3538 | for _index_0 = 1, 5 do |
2970 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
2971 | local item = _list_0[_index_0] | 3539 | local item = _list_0[_index_0] |
2972 | _accum_0[_len_0] = item | 3540 | _accum_0[_len_0] = item |
2973 | _len_0 = _len_0 + 1 | 3541 | _len_0 = _len_0 + 1 |
@@ -2977,7 +3545,8 @@ local slice | |||
2977 | local _accum_0 = { } | 3545 | local _accum_0 = { } |
2978 | local _len_0 = 1 | 3546 | local _len_0 = 1 |
2979 | local _list_0 = items | 3547 | local _list_0 = items |
2980 | for _index_0 = 2, #_list_0 do | 3548 | local _max_0 = #_list_0 |
3549 | for _index_0 = 2, _max_0 do | ||
2981 | local item = _list_0[_index_0] | 3550 | local item = _list_0[_index_0] |
2982 | _accum_0[_len_0] = item | 3551 | _accum_0[_len_0] = item |
2983 | _len_0 = _len_0 + 1 | 3552 | _len_0 = _len_0 + 1 |
@@ -2987,12 +3556,46 @@ local slice | |||
2987 | local _accum_0 = { } | 3556 | local _accum_0 = { } |
2988 | local _len_0 = 1 | 3557 | local _len_0 = 1 |
2989 | local _list_0 = items | 3558 | local _list_0 = items |
2990 | for _index_0 = 1, #_list_0, 2 do | 3559 | local _max_0 = #_list_0 |
3560 | for _index_0 = 1, _max_0, 2 do | ||
2991 | local item = _list_0[_index_0] | 3561 | local item = _list_0[_index_0] |
2992 | _accum_0[_len_0] = item | 3562 | _accum_0[_len_0] = item |
2993 | _len_0 = _len_0 + 1 | 3563 | _len_0 = _len_0 + 1 |
2994 | end | 3564 | end |
2995 | slice = _accum_0 | 3565 | slice = _accum_0 |
3566 | local slice | ||
3567 | local _accum_0 = { } | ||
3568 | local _len_0 = 1 | ||
3569 | local _list_0 = items | ||
3570 | local _min_0 = #_list_0 + -4 + 1 | ||
3571 | local _max_0 = #_list_0 + -1 + 1 | ||
3572 | for _index_0 = _min_0, _max_0 do | ||
3573 | local item = _list_0[_index_0] | ||
3574 | _accum_0[_len_0] = item | ||
3575 | _len_0 = _len_0 + 1 | ||
3576 | end | ||
3577 | slice = _accum_0 | ||
3578 | local reverse_slice | ||
3579 | local _accum_0 = { } | ||
3580 | local _len_0 = 1 | ||
3581 | local _list_0 = items | ||
3582 | local _min_0 = #_list_0 + -1 + 1 | ||
3583 | for _index_0 = _min_0, 1, -1 do | ||
3584 | local item = _list_0[_index_0] | ||
3585 | _accum_0[_len_0] = item | ||
3586 | _len_0 = _len_0 + 1 | ||
3587 | end | ||
3588 | reverse_slice = _accum_0 | ||
3589 | local sub_list | ||
3590 | local _accum_0 = { } | ||
3591 | local _len_0 = 1 | ||
3592 | local _list_0 = items | ||
3593 | for _index_0 = 2, 4 do | ||
3594 | local _item_0 = _list_0[_index_0] | ||
3595 | _accum_0[_len_0] = _item_0 | ||
3596 | _len_0 = _len_0 + 1 | ||
3597 | end | ||
3598 | sub_list = _accum_0 | ||
2996 | for i = 10, 20 do | 3599 | for i = 10, 20 do |
2997 | print(i) | 3600 | print(i) |
2998 | end | 3601 | end |
@@ -3003,8 +3606,7 @@ for key, value in pairs(object) do | |||
3003 | print(key, value) | 3606 | print(key, value) |
3004 | end | 3607 | end |
3005 | local _list_0 = items | 3608 | local _list_0 = items |
3006 | local _max_0 = 4 | 3609 | for _index_0 = 2, 4 do |
3007 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
3008 | local item = _list_0[_index_0] | 3610 | local item = _list_0[_index_0] |
3009 | print(item) | 3611 | print(item) |
3010 | end | 3612 | end |
@@ -3022,12 +3624,24 @@ local _len_0 = 1 | |||
3022 | for i = 1, 20 do | 3624 | for i = 1, 20 do |
3023 | if i % 2 == 0 then | 3625 | if i % 2 == 0 then |
3024 | _accum_0[_len_0] = i * 2 | 3626 | _accum_0[_len_0] = i * 2 |
3627 | _len_0 = _len_0 + 1 | ||
3025 | else | 3628 | else |
3026 | _accum_0[_len_0] = i | 3629 | _accum_0[_len_0] = i |
3630 | _len_0 = _len_0 + 1 | ||
3027 | end | 3631 | end |
3028 | _len_0 = _len_0 + 1 | ||
3029 | end | 3632 | end |
3030 | doubled_evens = _accum_0 | 3633 | doubled_evens = _accum_0 |
3634 | local first_large | ||
3635 | local _accum_0 | ||
3636 | local _list_0 = numbers | ||
3637 | for _index_0 = 1, #_list_0 do | ||
3638 | local n = _list_0[_index_0] | ||
3639 | if n > 10 then | ||
3640 | _accum_0 = n | ||
3641 | break | ||
3642 | end | ||
3643 | end | ||
3644 | first_large = _accum_0 | ||
3031 | local func_a | 3645 | local func_a |
3032 | func_a = function() | 3646 | func_a = function() |
3033 | for i = 1, 10 do | 3647 | for i = 1, 10 do |
@@ -3176,7 +3790,7 @@ if "Robert" == name then | |||
3176 | elseif "Dan" == name or "Daniel" == name then | 3790 | elseif "Dan" == name or "Daniel" == name then |
3177 | print("δ½ ηεεζ―Dan") | 3791 | print("δ½ ηεεζ―Dan") |
3178 | else | 3792 | else |
3179 | print("ζδΈη₯ιδ½ ηεε") | 3793 | print("ζδΈθ€θ―δ½ οΌδ½ ηεεζ―" .. tostring(name)) |
3180 | end | 3794 | end |
3181 | local b = 1 | 3795 | local b = 1 |
3182 | local next_number | 3796 | local next_number |
@@ -3276,6 +3890,192 @@ if _tab_0 then | |||
3276 | end | 3890 | end |
3277 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 3891 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
3278 | end | 3892 | end |
3893 | local _exp_0 = tb | ||
3894 | local _type_0 = type(_exp_0) | ||
3895 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
3896 | local _match_0 = false | ||
3897 | if _tab_0 then | ||
3898 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
3899 | _match_0 = true | ||
3900 | print("1, 2, 3") | ||
3901 | end | ||
3902 | end | ||
3903 | if not _match_0 then | ||
3904 | local _match_1 = false | ||
3905 | if _tab_0 then | ||
3906 | local b = _exp_0[2] | ||
3907 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
3908 | _match_1 = true | ||
3909 | print("1, " .. tostring(b) .. ", 3") | ||
3910 | end | ||
3911 | end | ||
3912 | if not _match_1 then | ||
3913 | if _tab_0 then | ||
3914 | local b = _exp_0[3] | ||
3915 | if b == nil then | ||
3916 | b = 3 | ||
3917 | end | ||
3918 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
3919 | print("1, 2, " .. tostring(b)) | ||
3920 | end | ||
3921 | end | ||
3922 | end | ||
3923 | end | ||
3924 | local _exp_0 = tb | ||
3925 | local _type_0 = type(_exp_0) | ||
3926 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
3927 | local _match_0 = false | ||
3928 | if _tab_0 then | ||
3929 | local result = _exp_0.result | ||
3930 | if true == _exp_0.success and result ~= nil then | ||
3931 | _match_0 = true | ||
3932 | print("ζε", result) | ||
3933 | end | ||
3934 | end | ||
3935 | if not _match_0 then | ||
3936 | local _match_1 = false | ||
3937 | if _tab_0 then | ||
3938 | if false == _exp_0.success then | ||
3939 | _match_1 = true | ||
3940 | print("ε€±θ΄₯", result) | ||
3941 | end | ||
3942 | end | ||
3943 | if not _match_1 then | ||
3944 | print("ζ ζεΌ") | ||
3945 | end | ||
3946 | end | ||
3947 | local _exp_0 = tb | ||
3948 | local _type_0 = type(_exp_0) | ||
3949 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
3950 | local _match_0 = false | ||
3951 | if _tab_0 then | ||
3952 | local content | ||
3953 | do | ||
3954 | local _obj_0 = _exp_0.data | ||
3955 | local _type_1 = type(_obj_0) | ||
3956 | if "table" == _type_1 or "userdata" == _type_1 then | ||
3957 | content = _obj_0.content | ||
3958 | end | ||
3959 | end | ||
3960 | local _val_0 | ||
3961 | do | ||
3962 | local _obj_0 = _exp_0.data | ||
3963 | if _obj_0 ~= nil then | ||
3964 | _val_0 = _obj_0.type | ||
3965 | end | ||
3966 | end | ||
3967 | if "success" == _val_0 and content ~= nil then | ||
3968 | _match_0 = true | ||
3969 | print("ζε", content) | ||
3970 | end | ||
3971 | end | ||
3972 | if not _match_0 then | ||
3973 | local _match_1 = false | ||
3974 | if _tab_0 then | ||
3975 | local content | ||
3976 | do | ||
3977 | local _obj_0 = _exp_0.data | ||
3978 | local _type_1 = type(_obj_0) | ||
3979 | if "table" == _type_1 or "userdata" == _type_1 then | ||
3980 | content = _obj_0.content | ||
3981 | end | ||
3982 | end | ||
3983 | local _val_0 | ||
3984 | do | ||
3985 | local _obj_0 = _exp_0.data | ||
3986 | if _obj_0 ~= nil then | ||
3987 | _val_0 = _obj_0.type | ||
3988 | end | ||
3989 | end | ||
3990 | if "error" == _val_0 and content ~= nil then | ||
3991 | _match_1 = true | ||
3992 | print("ε€±θ΄₯", content) | ||
3993 | end | ||
3994 | end | ||
3995 | if not _match_1 then | ||
3996 | print("ζ ζεΌ") | ||
3997 | end | ||
3998 | end | ||
3999 | local _exp_0 = tb | ||
4000 | local _type_0 = type(_exp_0) | ||
4001 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4002 | if _tab_0 then | ||
4003 | local fourth = _exp_0[4] | ||
4004 | local _val_0 | ||
4005 | do | ||
4006 | local _obj_0 = _exp_0[1] | ||
4007 | if _obj_0 ~= nil then | ||
4008 | _val_0 = _obj_0.a | ||
4009 | end | ||
4010 | end | ||
4011 | local _val_1 | ||
4012 | do | ||
4013 | local _obj_0 = _exp_0[1] | ||
4014 | if _obj_0 ~= nil then | ||
4015 | _val_1 = _obj_0.b | ||
4016 | end | ||
4017 | end | ||
4018 | local _val_2 | ||
4019 | do | ||
4020 | local _obj_0 = _exp_0[2] | ||
4021 | if _obj_0 ~= nil then | ||
4022 | _val_2 = _obj_0.a | ||
4023 | end | ||
4024 | end | ||
4025 | local _val_3 | ||
4026 | do | ||
4027 | local _obj_0 = _exp_0[2] | ||
4028 | if _obj_0 ~= nil then | ||
4029 | _val_3 = _obj_0.b | ||
4030 | end | ||
4031 | end | ||
4032 | local _val_4 | ||
4033 | do | ||
4034 | local _obj_0 = _exp_0[3] | ||
4035 | if _obj_0 ~= nil then | ||
4036 | _val_4 = _obj_0.a | ||
4037 | end | ||
4038 | end | ||
4039 | local _val_5 | ||
4040 | do | ||
4041 | local _obj_0 = _exp_0[3] | ||
4042 | if _obj_0 ~= nil then | ||
4043 | _val_5 = _obj_0.b | ||
4044 | end | ||
4045 | end | ||
4046 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
4047 | print("εΉι ζε", fourth) | ||
4048 | end | ||
4049 | end | ||
4050 | local segments = { | ||
4051 | "admin", | ||
4052 | "users", | ||
4053 | "logs", | ||
4054 | "view" | ||
4055 | } | ||
4056 | local _type_0 = type(segments) | ||
4057 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4058 | if _tab_0 then | ||
4059 | local groups | ||
4060 | do | ||
4061 | local _accum_0 = { } | ||
4062 | local _len_0 = 1 | ||
4063 | local _max_0 = #segments + -3 + 1 | ||
4064 | for _index_0 = 1, _max_0 do | ||
4065 | local _item_0 = segments[_index_0] | ||
4066 | _accum_0[_len_0] = _item_0 | ||
4067 | _len_0 = _len_0 + 1 | ||
4068 | end | ||
4069 | groups = _accum_0 | ||
4070 | end | ||
4071 | local resource = segments[#segments - 1] | ||
4072 | local action = segments[#segments] | ||
4073 | if resource ~= nil and action ~= nil then | ||
4074 | print("Group:", groups) | ||
4075 | print("Resource:", resource) | ||
4076 | print("Action:", action) | ||
4077 | end | ||
4078 | end | ||
3279 | local Inventory | 4079 | local Inventory |
3280 | local _class_0 | 4080 | local _class_0 |
3281 | local _base_0 = { | 4081 | local _base_0 = { |
@@ -3932,6 +4732,10 @@ do | |||
3932 | _with_1["key-name"] = value | 4732 | _with_1["key-name"] = value |
3933 | end | 4733 | end |
3934 | _with_0[#_with_0 + 1] = "abc" | 4734 | _with_0[#_with_0 + 1] = "abc" |
4735 | local _with_0 = obj | ||
4736 | if _with_0 ~= nil then | ||
4737 | print(obj.name) | ||
4738 | end | ||
3935 | do | 4739 | do |
3936 | local var = "hello" | 4740 | local var = "hello" |
3937 | print(var) | 4741 | print(var) |
diff --git a/spec/outputs/comprehension.lua b/spec/outputs/comprehension.lua index 9a7c478..663bd44 100644 --- a/spec/outputs/comprehension.lua +++ b/spec/outputs/comprehension.lua | |||
@@ -243,8 +243,11 @@ end | |||
243 | do | 243 | do |
244 | local _accum_0 = { } | 244 | local _accum_0 = { } |
245 | local _len_0 = 1 | 245 | local _len_0 = 1 |
246 | local _min_0 = 1 + 2 | ||
246 | local _max_0 = 3 + 4 | 247 | local _max_0 = 3 + 4 |
247 | for _index_0 = 1 + 2, _max_0 < 0 and #items + _max_0 or _max_0 do | 248 | _min_0 = _min_0 < 0 and #items + _min_0 + 1 or _min_0 |
249 | _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 | ||
250 | for _index_0 = _min_0, _max_0 do | ||
248 | local item = items[_index_0] | 251 | local item = items[_index_0] |
249 | _accum_0[_len_0] = item | 252 | _accum_0[_len_0] = item |
250 | _len_0 = _len_0 + 1 | 253 | _len_0 = _len_0 + 1 |
@@ -254,8 +257,11 @@ end | |||
254 | do | 257 | do |
255 | local _accum_0 = { } | 258 | local _accum_0 = { } |
256 | local _len_0 = 1 | 259 | local _len_0 = 1 |
260 | local _min_0 = hello() * 4 | ||
257 | local _max_0 = 2 - thing[4] | 261 | local _max_0 = 2 - thing[4] |
258 | for _index_0 = hello() * 4, _max_0 < 0 and #items + _max_0 or _max_0 do | 262 | _min_0 = _min_0 < 0 and #items + _min_0 + 1 or _min_0 |
263 | _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 | ||
264 | for _index_0 = _min_0, _max_0 do | ||
259 | local item = items[_index_0] | 265 | local item = items[_index_0] |
260 | _accum_0[_len_0] = item | 266 | _accum_0[_len_0] = item |
261 | _len_0 = _len_0 + 1 | 267 | _len_0 = _len_0 + 1 |
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 44da58b..ba216b5 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua | |||
@@ -621,4 +621,94 @@ do | |||
621 | print(meta_field, abc, def) | 621 | print(meta_field, abc, def) |
622 | end | 622 | end |
623 | end | 623 | end |
624 | do | ||
625 | local clients = { | ||
626 | "VIP_Alice", | ||
627 | "User_Bob", | ||
628 | "User_Clara", | ||
629 | "VIP_Eva" | ||
630 | } | ||
631 | local vipStart, regulars, vipEnd = clients[1], (function() | ||
632 | local _accum_0 = { } | ||
633 | local _len_0 = 1 | ||
634 | local _max_0 = #clients + -2 + 1 | ||
635 | for _index_0 = 2, _max_0 do | ||
636 | local _item_0 = clients[_index_0] | ||
637 | _accum_0[_len_0] = _item_0 | ||
638 | _len_0 = _len_0 + 1 | ||
639 | end | ||
640 | return _accum_0 | ||
641 | end)(), clients[#clients] | ||
642 | print(vipStart) | ||
643 | print(regulars) | ||
644 | print(vipEnd) | ||
645 | end | ||
646 | do | ||
647 | local setupMeeting | ||
648 | setupMeeting = function(participants) | ||
649 | local chair, secretary = participants[1], participants[#participants] | ||
650 | return print(chair, secretary) | ||
651 | end | ||
652 | setupMeeting({ | ||
653 | "Alice", | ||
654 | "Bob", | ||
655 | "Charlie", | ||
656 | "David" | ||
657 | }) | ||
658 | end | ||
659 | do | ||
660 | local getTransactions | ||
661 | getTransactions = function() | ||
662 | return { | ||
663 | { | ||
664 | id = "T1", | ||
665 | amount = 100 | ||
666 | }, | ||
667 | { | ||
668 | id = "T2", | ||
669 | amount = 200 | ||
670 | }, | ||
671 | { | ||
672 | id = "T3", | ||
673 | amount = 300 | ||
674 | } | ||
675 | } | ||
676 | end | ||
677 | local id, amount | ||
678 | do | ||
679 | local _item_0 = getTransactions() | ||
680 | local _obj_0 = _item_0[#_item_0] | ||
681 | id, amount = _obj_0.id, _obj_0.amount | ||
682 | end | ||
683 | assert(id == "T3") | ||
684 | assert(amount == 300) | ||
685 | end | ||
686 | do | ||
687 | local middle | ||
688 | local _accum_0 = { } | ||
689 | local _len_0 = 1 | ||
690 | local _list_0 = tb | ||
691 | local _max_0 = #_list_0 + -2 + 1 | ||
692 | for _index_0 = 2, _max_0 do | ||
693 | local _item_0 = _list_0[_index_0] | ||
694 | _accum_0[_len_0] = _item_0 | ||
695 | _len_0 = _len_0 + 1 | ||
696 | end | ||
697 | middle = _accum_0 | ||
698 | end | ||
699 | do | ||
700 | local a, abc, b, def, sub, d, e | ||
701 | local _obj_0 = tb | ||
702 | a, abc, b, def, sub, d, e = _obj_0[1], _obj_0.abc, _obj_0[2], _obj_0.def, (function() | ||
703 | local _accum_0 = { } | ||
704 | local _len_0 = 1 | ||
705 | local _max_0 = #_obj_0 + -3 + 1 | ||
706 | for _index_0 = 3, _max_0 do | ||
707 | local _item_0 = _obj_0[_index_0] | ||
708 | _accum_0[_len_0] = _item_0 | ||
709 | _len_0 = _len_0 + 1 | ||
710 | end | ||
711 | return _accum_0 | ||
712 | end)(), _obj_0[#_obj_0 - 1], _obj_0[#_obj_0] | ||
713 | end | ||
624 | return nil | 714 | return nil |
diff --git a/spec/outputs/global.lua b/spec/outputs/global.lua index 54a21a9..3918f85 100644 --- a/spec/outputs/global.lua +++ b/spec/outputs/global.lua | |||
@@ -93,3 +93,28 @@ do | |||
93 | FooBar = "pascal case" | 93 | FooBar = "pascal case" |
94 | FOOBAR = "all uppercase" | 94 | FOOBAR = "all uppercase" |
95 | end | 95 | end |
96 | do | ||
97 | do | ||
98 | local _class_0 | ||
99 | local _base_0 = { } | ||
100 | if _base_0.__index == nil then | ||
101 | _base_0.__index = _base_0 | ||
102 | end | ||
103 | _class_0 = setmetatable({ | ||
104 | __init = function() end, | ||
105 | __base = _base_0, | ||
106 | __name = "A" | ||
107 | }, { | ||
108 | __index = _base_0, | ||
109 | __call = function(cls, ...) | ||
110 | local _self_0 = setmetatable({ }, _base_0) | ||
111 | cls.__init(_self_0, ...) | ||
112 | return _self_0 | ||
113 | end | ||
114 | }) | ||
115 | _base_0.__class = _class_0 | ||
116 | A = _class_0 | ||
117 | end | ||
118 | Flag = 1 | ||
119 | const, x, y = "const", 1, 2 | ||
120 | end | ||
diff --git a/spec/outputs/import.lua b/spec/outputs/import.lua index 83c99e2..7aa130f 100644 --- a/spec/outputs/import.lua +++ b/spec/outputs/import.lua | |||
@@ -166,3 +166,13 @@ do | |||
166 | local _obj_1 = require("m") | 166 | local _obj_1 = require("m") |
167 | g, i = _obj_1[1], getmetatable(_obj_1[2]).__close | 167 | g, i = _obj_1[1], getmetatable(_obj_1[2]).__close |
168 | end | 168 | end |
169 | do | ||
170 | local require <const> = require | ||
171 | local stringlib <const> = string | ||
172 | local format <const> = string.format | ||
173 | local io_read <const> = io.read | ||
174 | local type | ||
175 | type = function() end | ||
176 | local tp <const> = _G.type | ||
177 | local yue <const> = _G["ζ"] | ||
178 | end | ||
diff --git a/spec/outputs/lists.lua b/spec/outputs/lists.lua index 48ec9c8..2ed7b95 100644 --- a/spec/outputs/lists.lua +++ b/spec/outputs/lists.lua | |||
@@ -230,31 +230,36 @@ x = { | |||
230 | 6, | 230 | 6, |
231 | 7 | 231 | 7 |
232 | } | 232 | } |
233 | local _max_0 = -5 | 233 | local _max_0 = #x + -5 + 1 |
234 | for _index_0 = 2, _max_0 < 0 and #x + _max_0 or _max_0, 2 do | 234 | for _index_0 = 2, _max_0, 2 do |
235 | local y = x[_index_0] | 235 | local y = x[_index_0] |
236 | print(y) | 236 | print(y) |
237 | end | 237 | end |
238 | local _max_1 = 3 | 238 | for _index_0 = 1, 3 do |
239 | for _index_0 = 1, _max_1 < 0 and #x + _max_1 or _max_1 do | ||
240 | local y = x[_index_0] | 239 | local y = x[_index_0] |
241 | print(y) | 240 | print(y) |
242 | end | 241 | end |
243 | for _index_0 = 2, #x do | 242 | local _max_1 = #x |
243 | for _index_0 = 2, _max_1 do | ||
244 | local y = x[_index_0] | 244 | local y = x[_index_0] |
245 | print(y) | 245 | print(y) |
246 | end | 246 | end |
247 | for _index_0 = 1, #x, 2 do | 247 | local _max_2 = #x |
248 | for _index_0 = 1, _max_2, 2 do | ||
248 | local y = x[_index_0] | 249 | local y = x[_index_0] |
249 | print(y) | 250 | print(y) |
250 | end | 251 | end |
251 | for _index_0 = 2, #x, 2 do | 252 | local _max_3 = #x |
253 | for _index_0 = 2, _max_3, 2 do | ||
252 | local y = x[_index_0] | 254 | local y = x[_index_0] |
253 | print(y) | 255 | print(y) |
254 | end | 256 | end |
255 | local a, b, c = 1, 5, 2 | 257 | local a, b, c = 1, 5, 2 |
256 | local _max_2 = b | 258 | local _min_0 = a |
257 | for _index_0 = a, _max_2 < 0 and #x + _max_2 or _max_2, c do | 259 | local _max_4 = b |
260 | _min_0 = _min_0 < 0 and #x + _min_0 + 1 or _min_0 | ||
261 | _max_4 = _max_4 < 0 and #x + _max_4 + 1 or _max_4 | ||
262 | for _index_0 = _min_0, _max_4, c do | ||
258 | local y = x[_index_0] | 263 | local y = x[_index_0] |
259 | print(y) | 264 | print(y) |
260 | end | 265 | end |
@@ -287,7 +292,10 @@ do | |||
287 | a | 292 | a |
288 | }) | 293 | }) |
289 | local _list_0 = f | 294 | local _list_0 = f |
290 | for _index_0 = a, #_list_0 do | 295 | local _min_1 = a |
296 | local _max_5 = #_list_0 | ||
297 | _min_1 = _min_1 < 0 and #_list_0 + _min_1 + 1 or _min_1 | ||
298 | for _index_0 = _min_1, _max_5 do | ||
291 | local v = _list_0[_index_0] | 299 | local v = _list_0[_index_0] |
292 | print(v) | 300 | print(v) |
293 | end | 301 | end |
@@ -327,4 +335,191 @@ do | |||
327 | job = "jobless" | 335 | job = "jobless" |
328 | end | 336 | end |
329 | end | 337 | end |
338 | do | ||
339 | local transactions = { | ||
340 | "T001", | ||
341 | "T002", | ||
342 | "T003", | ||
343 | "T004", | ||
344 | "T005" | ||
345 | } | ||
346 | local middleTransactions | ||
347 | do | ||
348 | local _accum_0 = { } | ||
349 | local _len_0 = 1 | ||
350 | local _max_5 = #transactions + -2 + 1 | ||
351 | for _index_0 = 2, _max_5 do | ||
352 | local _item_0 = transactions[_index_0] | ||
353 | _accum_0[_len_0] = _item_0 | ||
354 | _len_0 = _len_0 + 1 | ||
355 | end | ||
356 | middleTransactions = _accum_0 | ||
357 | end | ||
358 | print(middleTransactions) | ||
359 | end | ||
360 | do | ||
361 | local logs = { | ||
362 | { | ||
363 | start = 0, | ||
364 | ["end"] = 100 | ||
365 | }, | ||
366 | { | ||
367 | start = 100, | ||
368 | ["end"] = 200 | ||
369 | }, | ||
370 | { | ||
371 | start = 200, | ||
372 | ["end"] = 123 | ||
373 | } | ||
374 | } | ||
375 | print(logs[#logs]["end"]) | ||
376 | end | ||
377 | do | ||
378 | local pendingOrders = { | ||
379 | "O001", | ||
380 | "O002", | ||
381 | "O003", | ||
382 | "O004" | ||
383 | } | ||
384 | print(pendingOrders[#pendingOrders - 1]) | ||
385 | end | ||
386 | do | ||
387 | local getOrders | ||
388 | getOrders = function() | ||
389 | return { | ||
390 | { | ||
391 | id = "O1001", | ||
392 | status = "pending" | ||
393 | }, | ||
394 | { | ||
395 | id = "O1002", | ||
396 | status = "processing" | ||
397 | }, | ||
398 | { | ||
399 | id = "O1003", | ||
400 | status = "done" | ||
401 | } | ||
402 | } | ||
403 | end | ||
404 | local lastStatus | ||
405 | do | ||
406 | local _item_0 = getOrders() | ||
407 | lastStatus = _item_0[#_item_0].status | ||
408 | end | ||
409 | assert(lastStatus == "done") | ||
410 | end | ||
411 | do | ||
412 | local cloneList1 | ||
413 | cloneList1 = function(list) | ||
414 | local _accum_0 = { } | ||
415 | local _len_0 = 1 | ||
416 | local _max_5 = #list | ||
417 | for _index_0 = 1, _max_5 do | ||
418 | local _item_0 = list[_index_0] | ||
419 | _accum_0[_len_0] = _item_0 | ||
420 | _len_0 = _len_0 + 1 | ||
421 | end | ||
422 | return _accum_0 | ||
423 | end | ||
424 | local cloneList2 | ||
425 | cloneList2 = function(list) | ||
426 | local _tab_0 = { } | ||
427 | local _idx_0 = #_tab_0 + 1 | ||
428 | for _index_0 = 1, #list do | ||
429 | local _value_0 = list[_index_0] | ||
430 | _tab_0[_idx_0] = _value_0 | ||
431 | _idx_0 = _idx_0 + 1 | ||
432 | end | ||
433 | return _tab_0 | ||
434 | end | ||
435 | local cloneTable | ||
436 | cloneTable = function(tb) | ||
437 | local _tab_0 = { } | ||
438 | local _idx_0 = 1 | ||
439 | for _key_0, _value_0 in pairs(tb) do | ||
440 | if _idx_0 == _key_0 then | ||
441 | _tab_0[#_tab_0 + 1] = _value_0 | ||
442 | _idx_0 = _idx_0 + 1 | ||
443 | else | ||
444 | _tab_0[_key_0] = _value_0 | ||
445 | end | ||
446 | end | ||
447 | return _tab_0 | ||
448 | end | ||
449 | end | ||
450 | do | ||
451 | print((function() | ||
452 | local _item_0 = globalTB | ||
453 | return _item_0[#_item_0] | ||
454 | end)(), (function() | ||
455 | local _item_0 = a.b.c | ||
456 | return _item_0[#_item_0 - 2] | ||
457 | end)(), (function() | ||
458 | if x ~= nil then | ||
459 | local _obj_0 = x.y | ||
460 | if _obj_0 ~= nil then | ||
461 | local _obj_1 = _obj_0(x).z | ||
462 | if _obj_1 ~= nil then | ||
463 | return _obj_1[#_obj_1 - 3] | ||
464 | end | ||
465 | return nil | ||
466 | end | ||
467 | return nil | ||
468 | end | ||
469 | return nil | ||
470 | end)()) | ||
471 | end | ||
472 | local _anon_func_0 = function(globalTB) | ||
473 | local _item_0 = globalTB | ||
474 | local _call_0 = _item_0[#_item_0] | ||
475 | return _call_0["end"](_call_0, 123) | ||
476 | end | ||
477 | local _anon_func_1 = function(a) | ||
478 | local _item_0 | ||
479 | do | ||
480 | local _accum_0 = { } | ||
481 | local _len_0 = 1 | ||
482 | local _list_0 = a.b.c | ||
483 | local _max_5 = #_list_0 + -5 + 1 | ||
484 | for _index_0 = 5, _max_5 do | ||
485 | local _item_1 = _list_0[_index_0] | ||
486 | _accum_0[_len_0] = _item_1 | ||
487 | _len_0 = _len_0 + 1 | ||
488 | end | ||
489 | _item_0 = _accum_0 | ||
490 | end | ||
491 | return _item_0[#_item_0 - 2] | ||
492 | end | ||
493 | local _anon_func_2 = function(x) | ||
494 | if x ~= nil then | ||
495 | local _obj_0 = x.y | ||
496 | if _obj_0 ~= nil then | ||
497 | local _obj_1 = _obj_0(x).z | ||
498 | if _obj_1 ~= nil then | ||
499 | local _obj_2 = _obj_1[#_obj_1 - 3] | ||
500 | if _obj_2 ~= nil then | ||
501 | local _accum_0 = { } | ||
502 | local _len_0 = 1 | ||
503 | local _max_5 = #_obj_2 + -3 + 1 | ||
504 | for _index_0 = 1, _max_5 do | ||
505 | local _item_0 = _obj_2[_index_0] | ||
506 | _accum_0[_len_0] = _item_0 | ||
507 | _len_0 = _len_0 + 1 | ||
508 | end | ||
509 | return _accum_0 | ||
510 | end | ||
511 | return nil | ||
512 | end | ||
513 | return nil | ||
514 | end | ||
515 | return nil | ||
516 | end | ||
517 | return nil | ||
518 | end | ||
519 | do | ||
520 | local f | ||
521 | f = function() | ||
522 | return print(_anon_func_0(globalTB), _anon_func_1(a), _anon_func_2(x)) | ||
523 | end | ||
524 | end | ||
330 | return nil | 525 | return nil |
diff --git a/spec/outputs/literals.lua b/spec/outputs/literals.lua index a578d58..6de5411 100644 --- a/spec/outputs/literals.lua +++ b/spec/outputs/literals.lua | |||
@@ -8,10 +8,18 @@ local _ = { | |||
8 | 0xfF2323, | 8 | 0xfF2323, |
9 | 0xabcdef, | 9 | 0xabcdef, |
10 | 0xABCDEF, | 10 | 0xABCDEF, |
11 | 0XFBC400, | ||
11 | 0x123p-123, | 12 | 0x123p-123, |
12 | 0xABCP+321, | 13 | 0xABCP+321, |
13 | 0x.1p-111, | 14 | 0x.1p-111, |
14 | 0xABCP-321, | 15 | 0xABCP-321, |
16 | 0x0.1E, | ||
17 | 0xA23p-4, | ||
18 | 0X1.921FB54442D18P+1, | ||
19 | 1, | ||
20 | 8, | ||
21 | 15, | ||
22 | 201, | ||
15 | .2323, | 23 | .2323, |
16 | .2323e-1, | 24 | .2323e-1, |
17 | .2323e13434, | 25 | .2323e13434, |
diff --git a/spec/outputs/loops.lua b/spec/outputs/loops.lua index 8624d49..6ab4bbb 100644 --- a/spec/outputs/loops.lua +++ b/spec/outputs/loops.lua | |||
@@ -60,8 +60,8 @@ do | |||
60 | local y = hello[_index_0] | 60 | local y = hello[_index_0] |
61 | if y % 2 == 0 then | 61 | if y % 2 == 0 then |
62 | _accum_0[_len_0] = y | 62 | _accum_0[_len_0] = y |
63 | _len_0 = _len_0 + 1 | ||
63 | end | 64 | end |
64 | _len_0 = _len_0 + 1 | ||
65 | end | 65 | end |
66 | x = _accum_0 | 66 | x = _accum_0 |
67 | end | 67 | end |
@@ -132,13 +132,11 @@ do | |||
132 | end | 132 | end |
133 | do | 133 | do |
134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
135 | local _len_0 = 1 | ||
136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
138 | local thing = _list_2[_index_0] | 137 | local thing = _list_2[_index_0] |
139 | y = "hello" | 138 | y = "hello" |
140 | break | 139 | break |
141 | _len_0 = _len_0 + 1 | ||
142 | end | 140 | end |
143 | x = _accum_0 | 141 | x = _accum_0 |
144 | end | 142 | end |
@@ -370,3 +368,131 @@ do | |||
370 | end | 368 | end |
371 | until false | 369 | until false |
372 | end | 370 | end |
371 | local _anon_func_0 = function(i, tb) | ||
372 | local _accum_0 = { } | ||
373 | local _len_0 = 1 | ||
374 | while tb[i] do | ||
375 | i = i + 1 | ||
376 | _accum_0[_len_0] = i - 1 | ||
377 | _len_0 = _len_0 + 1 | ||
378 | end | ||
379 | return _accum_0 | ||
380 | end | ||
381 | do | ||
382 | local index | ||
383 | do | ||
384 | local _accum_0 | ||
385 | for i = 1, #tb do | ||
386 | if tb[i] then | ||
387 | _accum_0 = i | ||
388 | break | ||
389 | end | ||
390 | end | ||
391 | index = _accum_0 | ||
392 | end | ||
393 | f((function() | ||
394 | local _accum_0 | ||
395 | for i = 1, #tb do | ||
396 | if tb[i] then | ||
397 | _accum_0 = i | ||
398 | break | ||
399 | end | ||
400 | end | ||
401 | return _accum_0 | ||
402 | end)()) | ||
403 | f((function() | ||
404 | local _accum_0 = { } | ||
405 | local _len_0 = 1 | ||
406 | for i = 1, #tb do | ||
407 | if tb[i] then | ||
408 | _accum_0[_len_0] = i | ||
409 | _len_0 = _len_0 + 1 | ||
410 | end | ||
411 | end | ||
412 | return _accum_0 | ||
413 | end)()) | ||
414 | i = 1 | ||
415 | local ids | ||
416 | do | ||
417 | local _accum_0 = { } | ||
418 | local _len_0 = 1 | ||
419 | while tb[i] do | ||
420 | i = i + 1 | ||
421 | _accum_0[_len_0] = i - 1 | ||
422 | _len_0 = _len_0 + 1 | ||
423 | end | ||
424 | ids = _accum_0 | ||
425 | end | ||
426 | i = 1 | ||
427 | local idx | ||
428 | do | ||
429 | local _accum_0 | ||
430 | while tb[i] do | ||
431 | i = i + 1 | ||
432 | _accum_0 = i - 1 | ||
433 | break | ||
434 | end | ||
435 | idx = _accum_0 | ||
436 | end | ||
437 | local f1 | ||
438 | f1 = function() | ||
439 | i = 1 | ||
440 | return f(_anon_func_0(i, tb)) | ||
441 | end | ||
442 | i = 1 | ||
443 | f((function() | ||
444 | local _accum_0 | ||
445 | while tb[i] do | ||
446 | i = i + 1 | ||
447 | _accum_0 = i - 1 | ||
448 | break | ||
449 | end | ||
450 | return _accum_0 | ||
451 | end)()) | ||
452 | local _accum_0 = { } | ||
453 | local _len_0 = 1 | ||
454 | local _list_3 = items | ||
455 | for _index_0 = 1, #_list_3 do | ||
456 | local item = _list_3[_index_0] | ||
457 | local _type_0 = type(item) | ||
458 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
459 | if _tab_0 then | ||
460 | local value = item.value | ||
461 | if "A" == item.type and value ~= nil then | ||
462 | if value > 5 then | ||
463 | _accum_0[_len_0] = item | ||
464 | _len_0 = _len_0 + 1 | ||
465 | end | ||
466 | end | ||
467 | end | ||
468 | end | ||
469 | list = _accum_0 | ||
470 | end | ||
471 | do | ||
472 | repeat | ||
473 | print(1) | ||
474 | until true | ||
475 | do | ||
476 | local _accum_0 | ||
477 | repeat | ||
478 | a = func() | ||
479 | _accum_0 = a.x | ||
480 | break | ||
481 | until a.v | ||
482 | x = _accum_0 | ||
483 | end | ||
484 | local items | ||
485 | local _accum_0 = { } | ||
486 | local _len_0 = 1 | ||
487 | repeat | ||
488 | local item = getItem() | ||
489 | if not item then | ||
490 | break | ||
491 | end | ||
492 | if item.value > 0 then | ||
493 | _accum_0[_len_0] = item | ||
494 | _len_0 = _len_0 + 1 | ||
495 | end | ||
496 | until false | ||
497 | items = _accum_0 | ||
498 | end | ||
diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua index 4d31574..89c6e63 100644 --- a/spec/outputs/macro.lua +++ b/spec/outputs/macro.lua | |||
@@ -26,6 +26,10 @@ print({ | |||
26 | 123, | 26 | 123, |
27 | 'xyz' | 27 | 'xyz' |
28 | }) | 28 | }) |
29 | print({ | ||
30 | 456, | ||
31 | 'abc' | ||
32 | }) | ||
29 | do | 33 | do |
30 | assert(item == nil) | 34 | assert(item == nil) |
31 | end | 35 | end |
@@ -213,6 +217,13 @@ function tb:func() | |||
213 | end | 217 | end |
214 | end | 218 | end |
215 | print(x) | 219 | print(x) |
220 | local yue = require("yue") | ||
221 | do | ||
222 | local function f2(a) | ||
223 | return a + 1 | ||
224 | end | ||
225 | x = x + f2(3) | ||
226 | end | ||
216 | local sel | 227 | local sel |
217 | sel = function(a, b, c) | 228 | sel = function(a, b, c) |
218 | if a then | 229 | if a then |
@@ -317,7 +328,7 @@ print((setmetatable({ | |||
317 | return 998 | 328 | return 998 |
318 | end | 329 | end |
319 | })) | 330 | })) |
320 | print("current line: " .. tostring(323)) | 331 | print("current line: " .. tostring(349)) |
321 | do | 332 | do |
322 | do | 333 | do |
323 | -- TODO | 334 | -- TODO |
@@ -330,10 +341,8 @@ local _1 | |||
330 | _1 = function() | 341 | _1 = function() |
331 | print(1) | 342 | print(1) |
332 | local _accum_0 = { } | 343 | local _accum_0 = { } |
333 | local _len_0 = 1 | ||
334 | while false do | 344 | while false do |
335 | break | 345 | break |
336 | _len_0 = _len_0 + 1 | ||
337 | end | 346 | end |
338 | return _accum_0 | 347 | return _accum_0 |
339 | end | 348 | end |
diff --git a/spec/outputs/props.lua b/spec/outputs/props.lua new file mode 100644 index 0000000..2c282e0 --- /dev/null +++ b/spec/outputs/props.lua | |||
@@ -0,0 +1,240 @@ | |||
1 | local Props | ||
2 | do | ||
3 | local _class_0 | ||
4 | local assignReadOnly | ||
5 | local _base_0 = { | ||
6 | __index = function(self, name) | ||
7 | local cls = getmetatable(self) | ||
8 | do | ||
9 | local item | ||
10 | do | ||
11 | local _obj_0 = cls.__getter | ||
12 | if _obj_0 ~= nil then | ||
13 | item = _obj_0[name] | ||
14 | end | ||
15 | end | ||
16 | if item then | ||
17 | return item(self) | ||
18 | else | ||
19 | item = rawget(cls, name) | ||
20 | if item then | ||
21 | return item | ||
22 | else | ||
23 | local c = cls | ||
24 | repeat | ||
25 | c = getmetatable(c) | ||
26 | if c then | ||
27 | local _obj_0 = c.__getter | ||
28 | if _obj_0 ~= nil then | ||
29 | item = _obj_0[name] | ||
30 | end | ||
31 | if item then | ||
32 | if cls.__getter == nil then | ||
33 | cls.__getter = { } | ||
34 | end | ||
35 | cls.__getter[name] = item | ||
36 | return item(self) | ||
37 | else | ||
38 | item = rawget(c, name) | ||
39 | if item then | ||
40 | rawset(cls, name, item) | ||
41 | return item | ||
42 | end | ||
43 | end | ||
44 | else | ||
45 | break | ||
46 | end | ||
47 | until false | ||
48 | end | ||
49 | end | ||
50 | end | ||
51 | return nil | ||
52 | end, | ||
53 | __newindex = function(self, name, value) | ||
54 | local cls = getmetatable(self) | ||
55 | local item | ||
56 | local _obj_0 = cls.__setter | ||
57 | if _obj_0 ~= nil then | ||
58 | item = _obj_0[name] | ||
59 | end | ||
60 | if item then | ||
61 | return item(self, value) | ||
62 | else | ||
63 | local c = cls | ||
64 | repeat | ||
65 | c = getmetatable(c) | ||
66 | if c then | ||
67 | local _obj_1 = c.__setter | ||
68 | if _obj_1 ~= nil then | ||
69 | item = _obj_1[name] | ||
70 | end | ||
71 | if item then | ||
72 | if cls.__setter == nil then | ||
73 | cls.__setter = { } | ||
74 | end | ||
75 | cls.__setter[name] = item | ||
76 | item(self, value) | ||
77 | return | ||
78 | end | ||
79 | else | ||
80 | break | ||
81 | end | ||
82 | until false | ||
83 | return rawset(self, name, value) | ||
84 | end | ||
85 | end, | ||
86 | prop = function(self, name, props) | ||
87 | local get, set = props.get, props.set | ||
88 | if set == nil then | ||
89 | set = assignReadOnly | ||
90 | end | ||
91 | do | ||
92 | local getter = rawget(self.__base, "__getter") | ||
93 | if getter then | ||
94 | getter[name] = get | ||
95 | else | ||
96 | rawset(self.__base, "__getter", { | ||
97 | [name] = get | ||
98 | }) | ||
99 | end | ||
100 | end | ||
101 | local setter = rawget(self.__base, "__setter") | ||
102 | if setter then | ||
103 | setter[name] = set | ||
104 | else | ||
105 | return rawset(self.__base, "__setter", { | ||
106 | [name] = set | ||
107 | }) | ||
108 | end | ||
109 | end | ||
110 | } | ||
111 | if _base_0.__index == nil then | ||
112 | _base_0.__index = _base_0 | ||
113 | end | ||
114 | _class_0 = setmetatable({ | ||
115 | __init = function() end, | ||
116 | __base = _base_0, | ||
117 | __name = "Props" | ||
118 | }, { | ||
119 | __index = _base_0, | ||
120 | __call = function(cls, ...) | ||
121 | local _self_0 = setmetatable({ }, _base_0) | ||
122 | cls.__init(_self_0, ...) | ||
123 | return _self_0 | ||
124 | end | ||
125 | }) | ||
126 | _base_0.__class = _class_0 | ||
127 | local self = _class_0; | ||
128 | assignReadOnly = function() | ||
129 | return error("assigning a readonly property") | ||
130 | end | ||
131 | Props = _class_0 | ||
132 | end | ||
133 | local A | ||
134 | do | ||
135 | local _class_0 | ||
136 | local _parent_0 = Props | ||
137 | local _base_0 = { } | ||
138 | for _key_0, _val_0 in pairs(_parent_0.__base) do | ||
139 | if _base_0[_key_0] == nil and _key_0:match("^__") and not (_key_0 == "__index" and _val_0 == _parent_0.__base) then | ||
140 | _base_0[_key_0] = _val_0 | ||
141 | end | ||
142 | end | ||
143 | if _base_0.__index == nil then | ||
144 | _base_0.__index = _base_0 | ||
145 | end | ||
146 | setmetatable(_base_0, _parent_0.__base) | ||
147 | _class_0 = setmetatable({ | ||
148 | __init = function(self) | ||
149 | self._x = 0 | ||
150 | end, | ||
151 | __base = _base_0, | ||
152 | __name = "A", | ||
153 | __parent = _parent_0 | ||
154 | }, { | ||
155 | __index = function(cls, name) | ||
156 | local val = rawget(_base_0, name) | ||
157 | if val == nil then | ||
158 | local parent = rawget(cls, "__parent") | ||
159 | if parent then | ||
160 | return parent[name] | ||
161 | end | ||
162 | else | ||
163 | return val | ||
164 | end | ||
165 | end, | ||
166 | __call = function(cls, ...) | ||
167 | local _self_0 = setmetatable({ }, _base_0) | ||
168 | cls.__init(_self_0, ...) | ||
169 | return _self_0 | ||
170 | end | ||
171 | }) | ||
172 | _base_0.__class = _class_0 | ||
173 | local self = _class_0; | ||
174 | self:prop('x', { | ||
175 | get = function(self) | ||
176 | return self._x + 1000 | ||
177 | end, | ||
178 | set = function(self, v) | ||
179 | self._x = v | ||
180 | end | ||
181 | }) | ||
182 | if _parent_0.__inherited then | ||
183 | _parent_0.__inherited(_parent_0, _class_0) | ||
184 | end | ||
185 | A = _class_0 | ||
186 | end | ||
187 | local B | ||
188 | do | ||
189 | local _class_0 | ||
190 | local _parent_0 = A | ||
191 | local _base_0 = { } | ||
192 | for _key_0, _val_0 in pairs(_parent_0.__base) do | ||
193 | if _base_0[_key_0] == nil and _key_0:match("^__") and not (_key_0 == "__index" and _val_0 == _parent_0.__base) then | ||
194 | _base_0[_key_0] = _val_0 | ||
195 | end | ||
196 | end | ||
197 | if _base_0.__index == nil then | ||
198 | _base_0.__index = _base_0 | ||
199 | end | ||
200 | setmetatable(_base_0, _parent_0.__base) | ||
201 | _class_0 = setmetatable({ | ||
202 | __init = function(self, ...) | ||
203 | return _class_0.__parent.__init(self, ...) | ||
204 | end, | ||
205 | __base = _base_0, | ||
206 | __name = "B", | ||
207 | __parent = _parent_0 | ||
208 | }, { | ||
209 | __index = function(cls, name) | ||
210 | local val = rawget(_base_0, name) | ||
211 | if val == nil then | ||
212 | local parent = rawget(cls, "__parent") | ||
213 | if parent then | ||
214 | return parent[name] | ||
215 | end | ||
216 | else | ||
217 | return val | ||
218 | end | ||
219 | end, | ||
220 | __call = function(cls, ...) | ||
221 | local _self_0 = setmetatable({ }, _base_0) | ||
222 | cls.__init(_self_0, ...) | ||
223 | return _self_0 | ||
224 | end | ||
225 | }) | ||
226 | _base_0.__class = _class_0 | ||
227 | local self = _class_0; | ||
228 | self:prop('abc', { | ||
229 | get = function(self) | ||
230 | return "hello" | ||
231 | end | ||
232 | }) | ||
233 | if _parent_0.__inherited then | ||
234 | _parent_0.__inherited(_parent_0, _class_0) | ||
235 | end | ||
236 | B = _class_0 | ||
237 | end | ||
238 | local b = B() | ||
239 | b.x = 999 | ||
240 | return print(b.x, b.abc) | ||
diff --git a/spec/outputs/string.lua b/spec/outputs/string.lua index febea62..b536e6d 100644 --- a/spec/outputs/string.lua +++ b/spec/outputs/string.lua | |||
@@ -1,3 +1,4 @@ | |||
1 | local _module_0 = { } | ||
1 | local hi = "hello" | 2 | local hi = "hello" |
2 | local hello = "what the heckyes" | 3 | local hello = "what the heckyes" |
3 | print(hi) | 4 | print(hi) |
@@ -41,4 +42,42 @@ local _ = "hello"; | |||
41 | ("hello"):format().hello(1, 2, 3); | 42 | ("hello"):format().hello(1, 2, 3); |
42 | ("hello"):format(1, 2, 3) | 43 | ("hello"):format(1, 2, 3) |
43 | something("hello"):world() | 44 | something("hello"):world() |
44 | return something(("hello"):world()) | 45 | something(("hello"):world()) |
46 | do | ||
47 | local str = "key: value" | ||
48 | str = "config:\n\tenabled: true\n\tlevel: 5" | ||
49 | str = "header: start\nfooter: end" | ||
50 | str = "name: " .. tostring(username) | ||
51 | str = "count: " .. tostring(total) .. " items" | ||
52 | str = "user: " .. tostring(name) .. "\nid: " .. tostring(id) | ||
53 | str = "path: \"C:\\\\Program Files\\\\App\"\ndesc: 'single \"quote\" test'" | ||
54 | str = "key: value \nnext: 123 " | ||
55 | str = "list:\n - \"one\"\n - \"two\"" | ||
56 | str = "-- comment\ncontent text\n-- comment" | ||
57 | str = tostring(1 + 2) .. '\n' .. tostring(2 + 3) .. '\n' .. tostring("a" .. "b") | ||
58 | local obj = { | ||
59 | settings = "mode: " .. tostring(mode) .. "\nflags:\n\t- " .. tostring(flag1) .. "\n\t- default" | ||
60 | } | ||
61 | local fn | ||
62 | fn = function() | ||
63 | return "Hello\nname: " .. tostring(userName) | ||
64 | end | ||
65 | str = "result:\n\tstatus: " .. tostring((function() | ||
66 | if ok then | ||
67 | return "pass" | ||
68 | else | ||
69 | return "fail" | ||
70 | end | ||
71 | end)()) .. "\n\tcode: " .. tostring(code) | ||
72 | local summary = "date: " .. tostring(os.date()) .. "\nvalues:\n\t-\n\t\ta: " .. tostring(aVal) .. "\n\t\tb: " .. tostring(bVal or defaultB) | ||
73 | local msg = send("Hello, " .. tostring(user) .. "!\nToday is " .. tostring(os.date("%A")) .. ".") | ||
74 | local desc | ||
75 | do | ||
76 | local prefix = "Result" | ||
77 | desc = tostring(prefix) .. ":\nvalue: " .. tostring(compute()) | ||
78 | end | ||
79 | print(("1\n2\n3")) | ||
80 | end | ||
81 | local yaml = "version: " .. tostring(ver) .. "\nok: true" | ||
82 | _module_0["yaml"] = yaml | ||
83 | return _module_0 | ||
diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua index e4dedc9..7c1004b 100644 --- a/spec/outputs/switch.lua +++ b/spec/outputs/switch.lua | |||
@@ -415,4 +415,366 @@ do | |||
415 | end | 415 | end |
416 | end | 416 | end |
417 | end | 417 | end |
418 | do | ||
419 | local _exp_0 = tb | ||
420 | local _type_0 = type(_exp_0) | ||
421 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
422 | local _match_0 = false | ||
423 | if _tab_0 then | ||
424 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
425 | _match_0 = true | ||
426 | print("1, 2, 3") | ||
427 | end | ||
428 | end | ||
429 | if not _match_0 then | ||
430 | local _match_1 = false | ||
431 | if _tab_0 then | ||
432 | local b = _exp_0[2] | ||
433 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
434 | _match_1 = true | ||
435 | print("1, " .. tostring(b) .. ", 3") | ||
436 | end | ||
437 | end | ||
438 | if not _match_1 then | ||
439 | if _tab_0 then | ||
440 | local b = _exp_0[3] | ||
441 | if b == nil then | ||
442 | b = 3 | ||
443 | end | ||
444 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
445 | print("1, 2, " .. tostring(b)) | ||
446 | end | ||
447 | end | ||
448 | end | ||
449 | end | ||
450 | end | ||
451 | do | ||
452 | local _exp_0 = tb | ||
453 | local _type_0 = type(_exp_0) | ||
454 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
455 | local _match_0 = false | ||
456 | if _tab_0 then | ||
457 | local result = _exp_0.result | ||
458 | if true == _exp_0.success and result ~= nil then | ||
459 | _match_0 = true | ||
460 | print("success", result) | ||
461 | end | ||
462 | end | ||
463 | if not _match_0 then | ||
464 | local _match_1 = false | ||
465 | if _tab_0 then | ||
466 | if false == _exp_0.success then | ||
467 | _match_1 = true | ||
468 | print("failed", result) | ||
469 | end | ||
470 | end | ||
471 | if not _match_1 then | ||
472 | print("invalid") | ||
473 | end | ||
474 | end | ||
475 | end | ||
476 | do | ||
477 | local _exp_0 = tb | ||
478 | local _type_0 = type(_exp_0) | ||
479 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
480 | local _match_0 = false | ||
481 | if _tab_0 then | ||
482 | local content = _exp_0.content | ||
483 | if "success" == _exp_0.type and content ~= nil then | ||
484 | _match_0 = true | ||
485 | print("success", content) | ||
486 | end | ||
487 | end | ||
488 | if not _match_0 then | ||
489 | local _match_1 = false | ||
490 | if _tab_0 then | ||
491 | local content = _exp_0.content | ||
492 | if "error" == _exp_0.type and content ~= nil then | ||
493 | _match_1 = true | ||
494 | print("failed", content) | ||
495 | end | ||
496 | end | ||
497 | if not _match_1 then | ||
498 | print("invalid") | ||
499 | end | ||
500 | end | ||
501 | end | ||
502 | do | ||
503 | do | ||
504 | local _exp_0 = tb | ||
505 | local _type_0 = type(_exp_0) | ||
506 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
507 | if _tab_0 then | ||
508 | local fourth = _exp_0[4] | ||
509 | local _val_0 | ||
510 | do | ||
511 | local _obj_0 = _exp_0[1] | ||
512 | if _obj_0 ~= nil then | ||
513 | _val_0 = _obj_0.a | ||
514 | end | ||
515 | end | ||
516 | local _val_1 | ||
517 | do | ||
518 | local _obj_0 = _exp_0[1] | ||
519 | if _obj_0 ~= nil then | ||
520 | _val_1 = _obj_0.b | ||
521 | end | ||
522 | end | ||
523 | local _val_2 | ||
524 | do | ||
525 | local _obj_0 = _exp_0[2] | ||
526 | if _obj_0 ~= nil then | ||
527 | _val_2 = _obj_0.a | ||
528 | end | ||
529 | end | ||
530 | local _val_3 | ||
531 | do | ||
532 | local _obj_0 = _exp_0[2] | ||
533 | if _obj_0 ~= nil then | ||
534 | _val_3 = _obj_0.b | ||
535 | end | ||
536 | end | ||
537 | local _val_4 | ||
538 | do | ||
539 | local _obj_0 = _exp_0[3] | ||
540 | if _obj_0 ~= nil then | ||
541 | _val_4 = _obj_0.a | ||
542 | end | ||
543 | end | ||
544 | local _val_5 | ||
545 | do | ||
546 | local _obj_0 = _exp_0[3] | ||
547 | if _obj_0 ~= nil then | ||
548 | _val_5 = _obj_0.b | ||
549 | end | ||
550 | end | ||
551 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
552 | print("matched", fourth) | ||
553 | end | ||
554 | end | ||
555 | end | ||
556 | local _exp_0 = tb | ||
557 | local _type_0 = type(_exp_0) | ||
558 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
559 | local _match_0 = false | ||
560 | if _tab_0 then | ||
561 | local _val_0 | ||
562 | do | ||
563 | local _obj_0 = _exp_0[1] | ||
564 | if _obj_0 ~= nil then | ||
565 | _val_0 = _obj_0.c | ||
566 | end | ||
567 | end | ||
568 | local _val_1 | ||
569 | do | ||
570 | local _obj_0 = _exp_0[1] | ||
571 | if _obj_0 ~= nil then | ||
572 | _val_1 = _obj_0.d | ||
573 | end | ||
574 | end | ||
575 | local _val_2 | ||
576 | do | ||
577 | local _obj_0 = _exp_0[2] | ||
578 | if _obj_0 ~= nil then | ||
579 | _val_2 = _obj_0.c | ||
580 | end | ||
581 | end | ||
582 | local _val_3 | ||
583 | do | ||
584 | local _obj_0 = _exp_0[2] | ||
585 | if _obj_0 ~= nil then | ||
586 | _val_3 = _obj_0.d | ||
587 | end | ||
588 | end | ||
589 | local _val_4 | ||
590 | do | ||
591 | local _obj_0 = _exp_0[3] | ||
592 | if _obj_0 ~= nil then | ||
593 | _val_4 = _obj_0.c | ||
594 | end | ||
595 | end | ||
596 | local _val_5 | ||
597 | do | ||
598 | local _obj_0 = _exp_0[3] | ||
599 | if _obj_0 ~= nil then | ||
600 | _val_5 = _obj_0.d | ||
601 | end | ||
602 | end | ||
603 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 then | ||
604 | _match_0 = true | ||
605 | print("OK") | ||
606 | end | ||
607 | end | ||
608 | if not _match_0 then | ||
609 | if _tab_0 then | ||
610 | local sixth = _exp_0[6] | ||
611 | local _val_0 | ||
612 | do | ||
613 | local _obj_0 = _exp_0[3] | ||
614 | if _obj_0 ~= nil then | ||
615 | _val_0 = _obj_0.a | ||
616 | end | ||
617 | end | ||
618 | local _val_1 | ||
619 | do | ||
620 | local _obj_0 = _exp_0[3] | ||
621 | if _obj_0 ~= nil then | ||
622 | _val_1 = _obj_0.b | ||
623 | end | ||
624 | end | ||
625 | local _val_2 | ||
626 | do | ||
627 | local _obj_0 = _exp_0[4] | ||
628 | if _obj_0 ~= nil then | ||
629 | _val_2 = _obj_0.a | ||
630 | end | ||
631 | end | ||
632 | local _val_3 | ||
633 | do | ||
634 | local _obj_0 = _exp_0[4] | ||
635 | if _obj_0 ~= nil then | ||
636 | _val_3 = _obj_0.b | ||
637 | end | ||
638 | end | ||
639 | local _val_4 | ||
640 | do | ||
641 | local _obj_0 = _exp_0[5] | ||
642 | if _obj_0 ~= nil then | ||
643 | _val_4 = _obj_0.a | ||
644 | end | ||
645 | end | ||
646 | local _val_5 | ||
647 | do | ||
648 | local _obj_0 = _exp_0[5] | ||
649 | if _obj_0 ~= nil then | ||
650 | _val_5 = _obj_0.b | ||
651 | end | ||
652 | end | ||
653 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and sixth ~= nil then | ||
654 | print("matched", sixth) | ||
655 | end | ||
656 | end | ||
657 | end | ||
658 | end | ||
659 | do | ||
660 | local v = "hello" | ||
661 | if "hello" == v then | ||
662 | print("matched hello") | ||
663 | else | ||
664 | print("not matched") | ||
665 | end | ||
666 | end | ||
667 | do | ||
668 | local f | ||
669 | f = function() | ||
670 | return "ok" | ||
671 | end | ||
672 | local val = f() | ||
673 | if "ok" == val then | ||
674 | print("it's ok") | ||
675 | end | ||
676 | end | ||
677 | do | ||
678 | local g | ||
679 | g = function() | ||
680 | return 42 | ||
681 | end | ||
682 | local result = g() | ||
683 | if 1 == result or 2 == result then | ||
684 | print("small") | ||
685 | elseif 42 == result then | ||
686 | print("life universe everything") | ||
687 | else | ||
688 | print("other " .. tostring(result)) | ||
689 | end | ||
690 | end | ||
691 | do | ||
692 | local check | ||
693 | check = function() | ||
694 | if true then | ||
695 | return "yes" | ||
696 | else | ||
697 | return "no" | ||
698 | end | ||
699 | end | ||
700 | local x = check() | ||
701 | if "yes" == x then | ||
702 | print("affirmative") | ||
703 | else | ||
704 | print("negative") | ||
705 | end | ||
706 | end | ||
707 | do | ||
708 | local t | ||
709 | t = function() | ||
710 | local tb = { | ||
711 | a = 1 | ||
712 | } | ||
713 | tb.a = 2 | ||
714 | return tb | ||
715 | end | ||
716 | local data = t() | ||
717 | local _type_0 = type(data) | ||
718 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
719 | local _match_0 = false | ||
720 | if _tab_0 then | ||
721 | if 2 == data.a then | ||
722 | _match_0 = true | ||
723 | print("matched") | ||
724 | end | ||
725 | end | ||
726 | if not _match_0 then | ||
727 | print("not matched") | ||
728 | end | ||
729 | end | ||
730 | do | ||
731 | local clientData = { | ||
732 | "Meta", | ||
733 | "CUST_1001", | ||
734 | "CHK123" | ||
735 | } | ||
736 | local _type_0 = type(clientData) | ||
737 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
738 | if _tab_0 then | ||
739 | local metadata | ||
740 | do | ||
741 | local _accum_0 = { } | ||
742 | local _len_0 = 1 | ||
743 | local _max_0 = #clientData + -3 + 1 | ||
744 | for _index_0 = 1, _max_0 do | ||
745 | local _item_0 = clientData[_index_0] | ||
746 | _accum_0[_len_0] = _item_0 | ||
747 | _len_0 = _len_0 + 1 | ||
748 | end | ||
749 | metadata = _accum_0 | ||
750 | end | ||
751 | local customerId = clientData[#clientData - 1] | ||
752 | local checksum = clientData[#clientData] | ||
753 | if customerId ~= nil and checksum ~= nil then | ||
754 | print(metadata) | ||
755 | print(customerId) | ||
756 | print(checksum) | ||
757 | end | ||
758 | end | ||
759 | end | ||
760 | do | ||
761 | local handlePath | ||
762 | handlePath = function(segments) | ||
763 | local _type_0 = type(segments) | ||
764 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
765 | if _tab_0 then | ||
766 | local resource = segments[#segments - 1] | ||
767 | local action = segments[#segments] | ||
768 | if resource ~= nil and action ~= nil then | ||
769 | print("Resource:", resource) | ||
770 | return print("Action:", action) | ||
771 | end | ||
772 | end | ||
773 | end | ||
774 | handlePath({ | ||
775 | "admin", | ||
776 | "logs", | ||
777 | "view" | ||
778 | }) | ||
779 | end | ||
418 | return nil | 780 | return nil |
diff --git a/spec/outputs/tables.lua b/spec/outputs/tables.lua index f358811..3f851de 100644 --- a/spec/outputs/tables.lua +++ b/spec/outputs/tables.lua | |||
@@ -366,6 +366,28 @@ local menus = { | |||
366 | } | 366 | } |
367 | } | 367 | } |
368 | } | 368 | } |
369 | _ = { | ||
370 | boolean = { | ||
371 | true, | ||
372 | false | ||
373 | }, | ||
374 | float = { | ||
375 | 3.14, | ||
376 | -6.8523015e+5 | ||
377 | }, | ||
378 | int = { | ||
379 | 123, | ||
380 | -685230 | ||
381 | }, | ||
382 | null = { | ||
383 | nodeName = 'node', | ||
384 | parent = nil | ||
385 | }, | ||
386 | string = { | ||
387 | 'Hello world', | ||
388 | "newline\nnewline2" | ||
389 | } | ||
390 | } | ||
369 | local tb | 391 | local tb |
370 | do | 392 | do |
371 | local _tab_0 = { } | 393 | local _tab_0 = { } |
diff --git a/spec/outputs/try_catch.lua b/spec/outputs/try_catch.lua index efd92c6..edb2341 100644 --- a/spec/outputs/try_catch.lua +++ b/spec/outputs/try_catch.lua | |||
@@ -22,6 +22,44 @@ end | |||
22 | local _anon_func_7 = function(a, b, c, tb) | 22 | local _anon_func_7 = function(a, b, c, tb) |
23 | return tb.f(a, b, c) | 23 | return tb.f(a, b, c) |
24 | end | 24 | end |
25 | local _anon_func_8 = function(_arg_0, ...) | ||
26 | local ok = _arg_0 | ||
27 | return ... | ||
28 | end | ||
29 | local _anon_func_10 = function(_arg_0, ...) | ||
30 | local _ok_0 = _arg_0 | ||
31 | if _ok_0 then | ||
32 | return ... | ||
33 | end | ||
34 | end | ||
35 | local _anon_func_9 = function(func, pcall) | ||
36 | return _anon_func_10(pcall(func)) | ||
37 | end | ||
38 | local _anon_func_12 = function(_arg_0, ...) | ||
39 | local _ok_0 = _arg_0 | ||
40 | if _ok_0 then | ||
41 | return ... | ||
42 | end | ||
43 | end | ||
44 | local _anon_func_11 = function(func, pcall) | ||
45 | return _anon_func_12(pcall(func)) | ||
46 | end | ||
47 | local _anon_func_14 = function(_arg_0, ...) | ||
48 | local _ok_0 = _arg_0 | ||
49 | if _ok_0 then | ||
50 | return ... | ||
51 | end | ||
52 | end | ||
53 | local _anon_func_15 = function(func, print) | ||
54 | print(123) | ||
55 | return func() | ||
56 | end | ||
57 | local _anon_func_13 = function(func, print, xpcall) | ||
58 | return _anon_func_14(xpcall(_anon_func_15, function(e) | ||
59 | print(e) | ||
60 | return e | ||
61 | end, func, print)) | ||
62 | end | ||
25 | local f | 63 | local f |
26 | f = function() | 64 | f = function() |
27 | xpcall(function() | 65 | xpcall(function() |
@@ -104,10 +142,236 @@ f = function() | |||
104 | do | 142 | do |
105 | x(function() | 143 | x(function() |
106 | local tb, a, b, c | 144 | local tb, a, b, c |
107 | f = function() | 145 | local f1 |
146 | f1 = function() | ||
108 | return pcall(_anon_func_7, a, b, c, tb) | 147 | return pcall(_anon_func_7, a, b, c, tb) |
109 | end | 148 | end |
110 | end) | 149 | end) |
111 | end | 150 | end |
151 | do | ||
152 | local f1 | ||
153 | f1 = function() | ||
154 | do | ||
155 | return _anon_func_8(pcall(function() | ||
156 | return func() | ||
157 | end)) | ||
158 | end | ||
159 | end | ||
160 | end | ||
161 | do | ||
162 | local func | ||
163 | local a, b, c | ||
164 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
165 | if _ok_0 then | ||
166 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
167 | end | ||
168 | end | ||
169 | do | ||
170 | local a, b, c | ||
171 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
172 | return func() | ||
173 | end) | ||
174 | if _ok_0 then | ||
175 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
176 | end | ||
177 | end | ||
178 | do | ||
179 | local a | ||
180 | local _exp_0 = (_anon_func_9(func, pcall)) | ||
181 | if _exp_0 ~= nil then | ||
182 | a = _exp_0 | ||
183 | else | ||
184 | a = "default" | ||
185 | end | ||
186 | end | ||
187 | do | ||
188 | f(_anon_func_11(func, pcall)) | ||
189 | end | ||
190 | do | ||
191 | f(_anon_func_13(func, print, xpcall)) | ||
192 | end | ||
112 | return nil | 193 | return nil |
113 | end | 194 | end |
195 | local _anon_func_16 = function(a, b, c, tb) | ||
196 | return tb.f(a, b, c) | ||
197 | end | ||
198 | local _anon_func_17 = function(_arg_0, ...) | ||
199 | local ok = _arg_0 | ||
200 | return ... | ||
201 | end | ||
202 | do | ||
203 | xpcall(function() | ||
204 | return func(1, 2, 3) | ||
205 | end, function(err) | ||
206 | return print(err) | ||
207 | end) | ||
208 | xpcall(function() | ||
209 | return func(1, 2, 3) | ||
210 | end, function(err) | ||
211 | return print(err) | ||
212 | end) | ||
213 | pcall(function() | ||
214 | print("trying") | ||
215 | return func(1, 2, 3) | ||
216 | end) | ||
217 | do | ||
218 | local success, result = xpcall(function() | ||
219 | return func(1, 2, 3) | ||
220 | end, function(err) | ||
221 | return print(err) | ||
222 | end) | ||
223 | success, result = pcall(function() | ||
224 | return func(1, 2, 3) | ||
225 | end) | ||
226 | end | ||
227 | local tb = { } | ||
228 | pcall(function() | ||
229 | return tb.func | ||
230 | end) | ||
231 | pcall(function() | ||
232 | return tb.func() | ||
233 | end) | ||
234 | pcall(function() | ||
235 | return tb.func() | ||
236 | end) | ||
237 | pcall(function() | ||
238 | return (tb.func()) | ||
239 | end) | ||
240 | pcall(function() | ||
241 | return (tb:func(1, 2, 3)) | ||
242 | end) | ||
243 | pcall(function() | ||
244 | return tb.func(1) | ||
245 | end) | ||
246 | pcall(function() | ||
247 | return tb.func(1) | ||
248 | end) | ||
249 | if (xpcall(function() | ||
250 | return func(1) | ||
251 | end, function(err) | ||
252 | return print(err) | ||
253 | end)) then | ||
254 | print("OK") | ||
255 | end | ||
256 | if xpcall(function() | ||
257 | return (func(1)) | ||
258 | end, function(err) | ||
259 | return print(err) | ||
260 | end) then | ||
261 | print("OK") | ||
262 | end | ||
263 | do | ||
264 | do | ||
265 | local success, result = pcall(function() | ||
266 | return func("abc", 123) | ||
267 | end) | ||
268 | if success then | ||
269 | print(result) | ||
270 | end | ||
271 | end | ||
272 | local success, result = xpcall(function() | ||
273 | return func("abc", 123) | ||
274 | end, function(err) | ||
275 | return print(err) | ||
276 | end) | ||
277 | success, result = xpcall(function() | ||
278 | return func("abc", 123) | ||
279 | end, function(err) | ||
280 | return print(err) | ||
281 | end) | ||
282 | if success then | ||
283 | print(result) | ||
284 | end | ||
285 | end | ||
286 | do | ||
287 | pcall(function() | ||
288 | return func(1, 2, 3) | ||
289 | end) | ||
290 | pcall(function() | ||
291 | return func(1, 2, 3) | ||
292 | end) | ||
293 | end | ||
294 | do | ||
295 | x(function() | ||
296 | local tb, a, b, c | ||
297 | local f1 | ||
298 | f1 = function() | ||
299 | return pcall(_anon_func_16, a, b, c, tb) | ||
300 | end | ||
301 | end) | ||
302 | end | ||
303 | do | ||
304 | local f1 | ||
305 | f1 = function() | ||
306 | do | ||
307 | return _anon_func_17(pcall(function() | ||
308 | return func() | ||
309 | end)) | ||
310 | end | ||
311 | end | ||
312 | end | ||
313 | do | ||
314 | local func | ||
315 | local a, b, c | ||
316 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
317 | if _ok_0 then | ||
318 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
319 | end | ||
320 | end | ||
321 | do | ||
322 | local a, b, c | ||
323 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
324 | return func() | ||
325 | end) | ||
326 | if _ok_0 then | ||
327 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
328 | end | ||
329 | end | ||
330 | do | ||
331 | local a | ||
332 | local _exp_0 = ((function() | ||
333 | return (function(_arg_0, ...) | ||
334 | local _ok_0 = _arg_0 | ||
335 | if _ok_0 then | ||
336 | return ... | ||
337 | end | ||
338 | end)(pcall(function() | ||
339 | return func() | ||
340 | end)) | ||
341 | end)()) | ||
342 | if _exp_0 ~= nil then | ||
343 | a = _exp_0 | ||
344 | else | ||
345 | a = "default" | ||
346 | end | ||
347 | end | ||
348 | do | ||
349 | f((function() | ||
350 | return (function(_arg_0, ...) | ||
351 | local _ok_0 = _arg_0 | ||
352 | if _ok_0 then | ||
353 | return ... | ||
354 | end | ||
355 | end)(pcall(function() | ||
356 | return func() | ||
357 | end)) | ||
358 | end)()) | ||
359 | end | ||
360 | do | ||
361 | f((function() | ||
362 | return (function(_arg_0, ...) | ||
363 | local _ok_0 = _arg_0 | ||
364 | if _ok_0 then | ||
365 | return ... | ||
366 | end | ||
367 | end)(xpcall(function() | ||
368 | print(123) | ||
369 | return func() | ||
370 | end, function(e) | ||
371 | print(e) | ||
372 | return e | ||
373 | end)) | ||
374 | end)()) | ||
375 | end | ||
376 | end | ||
377 | return nil | ||
diff --git a/spec/outputs/unicode/assign.lua b/spec/outputs/unicode/assign.lua index d4ad56a..e00d016 100644 --- a/spec/outputs/unicode/assign.lua +++ b/spec/outputs/unicode/assign.lua | |||
@@ -43,10 +43,8 @@ do | |||
43 | end | 43 | end |
44 | end | 44 | end |
45 | local _anon_func_0 = function(_u6253_u5370) | 45 | local _anon_func_0 = function(_u6253_u5370) |
46 | do | 46 | _u6253_u5370(123) |
47 | _u6253_u5370(123) | 47 | return { } |
48 | return { } | ||
49 | end | ||
50 | end | 48 | end |
51 | return __u65e0_u6548_u53d8_u91cf(function() | 49 | return __u65e0_u6548_u53d8_u91cf(function() |
52 | setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370)) | 50 | setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370)) |
diff --git a/spec/outputs/unicode/comprehension.lua b/spec/outputs/unicode/comprehension.lua index 60e490f..92bce69 100644 --- a/spec/outputs/unicode/comprehension.lua +++ b/spec/outputs/unicode/comprehension.lua | |||
@@ -243,8 +243,11 @@ end | |||
243 | do | 243 | do |
244 | local _accum_0 = { } | 244 | local _accum_0 = { } |
245 | local _len_0 = 1 | 245 | local _len_0 = 1 |
246 | local _min_0 = 1 + 2 | ||
246 | local _max_0 = 3 + 4 | 247 | local _max_0 = 3 + 4 |
247 | for _index_0 = 1 + 2, _max_0 < 0 and #_u5217_u8868 + _max_0 or _max_0 do | 248 | _min_0 = _min_0 < 0 and #_u5217_u8868 + _min_0 + 1 or _min_0 |
249 | _max_0 = _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 | ||
250 | for _index_0 = _min_0, _max_0 do | ||
248 | local _u9879_u76ee = _u5217_u8868[_index_0] | 251 | local _u9879_u76ee = _u5217_u8868[_index_0] |
249 | _accum_0[_len_0] = _u9879_u76ee | 252 | _accum_0[_len_0] = _u9879_u76ee |
250 | _len_0 = _len_0 + 1 | 253 | _len_0 = _len_0 + 1 |
@@ -254,8 +257,11 @@ end | |||
254 | do | 257 | do |
255 | local _accum_0 = { } | 258 | local _accum_0 = { } |
256 | local _len_0 = 1 | 259 | local _len_0 = 1 |
260 | local _min_0 = _u4f60_u597d() * 4 | ||
257 | local _max_0 = 2 - _u4e1c_u897f[4] | 261 | local _max_0 = 2 - _u4e1c_u897f[4] |
258 | for _index_0 = _u4f60_u597d() * 4, _max_0 < 0 and #_u5217_u8868 + _max_0 or _max_0 do | 262 | _min_0 = _min_0 < 0 and #_u5217_u8868 + _min_0 + 1 or _min_0 |
263 | _max_0 = _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 | ||
264 | for _index_0 = _min_0, _max_0 do | ||
259 | local _u9879_u76ee = _u5217_u8868[_index_0] | 265 | local _u9879_u76ee = _u5217_u8868[_index_0] |
260 | _accum_0[_len_0] = _u9879_u76ee | 266 | _accum_0[_len_0] = _u9879_u76ee |
261 | _len_0 = _len_0 + 1 | 267 | _len_0 = _len_0 + 1 |
diff --git a/spec/outputs/unicode/lists.lua b/spec/outputs/unicode/lists.lua index aafd516..3bf6f50 100644 --- a/spec/outputs/unicode/lists.lua +++ b/spec/outputs/unicode/lists.lua | |||
@@ -229,31 +229,36 @@ _u53d8_u91cfx = { | |||
229 | 6, | 229 | 6, |
230 | 7 | 230 | 7 |
231 | } | 231 | } |
232 | local _max_0 = -5 | 232 | local _max_0 = #_u53d8_u91cfx + -5 + 1 |
233 | for _index_0 = 2, _max_0 < 0 and #_u53d8_u91cfx + _max_0 or _max_0, 2 do | 233 | for _index_0 = 2, _max_0, 2 do |
234 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 234 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
235 | _u6253_u5370(_u53d8_u91cfy) | 235 | _u6253_u5370(_u53d8_u91cfy) |
236 | end | 236 | end |
237 | local _max_1 = 3 | 237 | for _index_0 = 1, 3 do |
238 | for _index_0 = 1, _max_1 < 0 and #_u53d8_u91cfx + _max_1 or _max_1 do | ||
239 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 238 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
240 | _u6253_u5370(_u53d8_u91cfy) | 239 | _u6253_u5370(_u53d8_u91cfy) |
241 | end | 240 | end |
242 | for _index_0 = 2, #_u53d8_u91cfx do | 241 | local _max_1 = #_u53d8_u91cfx |
242 | for _index_0 = 2, _max_1 do | ||
243 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 243 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
244 | _u6253_u5370(_u53d8_u91cfy) | 244 | _u6253_u5370(_u53d8_u91cfy) |
245 | end | 245 | end |
246 | for _index_0 = 1, #_u53d8_u91cfx, 2 do | 246 | local _max_2 = #_u53d8_u91cfx |
247 | for _index_0 = 1, _max_2, 2 do | ||
247 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 248 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
248 | _u6253_u5370(_u53d8_u91cfy) | 249 | _u6253_u5370(_u53d8_u91cfy) |
249 | end | 250 | end |
250 | for _index_0 = 2, #_u53d8_u91cfx, 2 do | 251 | local _max_3 = #_u53d8_u91cfx |
252 | for _index_0 = 2, _max_3, 2 do | ||
251 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 253 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
252 | _u6253_u5370(_u53d8_u91cfy) | 254 | _u6253_u5370(_u53d8_u91cfy) |
253 | end | 255 | end |
254 | local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2 | 256 | local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2 |
255 | local _max_2 = _u53d8_u91cfb | 257 | local _min_0 = _u53d8_u91cfa |
256 | for _index_0 = _u53d8_u91cfa, _max_2 < 0 and #_u53d8_u91cfx + _max_2 or _max_2, _u53d8_u91cfc do | 258 | local _max_4 = _u53d8_u91cfb |
259 | _min_0 = _min_0 < 0 and #_u53d8_u91cfx + _min_0 + 1 or _min_0 | ||
260 | _max_4 = _max_4 < 0 and #_u53d8_u91cfx + _max_4 + 1 or _max_4 | ||
261 | for _index_0 = _min_0, _max_4, _u53d8_u91cfc do | ||
257 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 262 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
258 | _u6253_u5370(_u53d8_u91cfy) | 263 | _u6253_u5370(_u53d8_u91cfy) |
259 | end | 264 | end |
diff --git a/spec/outputs/unicode/loops.lua b/spec/outputs/unicode/loops.lua index 8379993..27bbe2e 100644 --- a/spec/outputs/unicode/loops.lua +++ b/spec/outputs/unicode/loops.lua | |||
@@ -60,8 +60,8 @@ do | |||
60 | local _u53d8_u91cfy = _u4f60_u597d[_index_0] | 60 | local _u53d8_u91cfy = _u4f60_u597d[_index_0] |
61 | if _u53d8_u91cfy % 2 == 0 then | 61 | if _u53d8_u91cfy % 2 == 0 then |
62 | _accum_0[_len_0] = _u53d8_u91cfy | 62 | _accum_0[_len_0] = _u53d8_u91cfy |
63 | _len_0 = _len_0 + 1 | ||
63 | end | 64 | end |
64 | _len_0 = _len_0 + 1 | ||
65 | end | 65 | end |
66 | _u53d8_u91cfx = _accum_0 | 66 | _u53d8_u91cfx = _accum_0 |
67 | end | 67 | end |
@@ -132,13 +132,11 @@ do | |||
132 | end | 132 | end |
133 | do | 133 | do |
134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
135 | local _len_0 = 1 | ||
136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
138 | local _u4e1c_u897f = _list_2[_index_0] | 137 | local _u4e1c_u897f = _list_2[_index_0] |
139 | _u53d8_u91cfy = "δ½ ε₯½" | 138 | _u53d8_u91cfy = "δ½ ε₯½" |
140 | break | 139 | break |
141 | _len_0 = _len_0 + 1 | ||
142 | end | 140 | end |
143 | _u53d8_u91cfx = _accum_0 | 141 | _u53d8_u91cfx = _accum_0 |
144 | end | 142 | end |
diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua index b14f571..b4e78cd 100644 --- a/spec/outputs/unicode/macro.lua +++ b/spec/outputs/unicode/macro.lua | |||
@@ -216,17 +216,15 @@ do | |||
216 | end | 216 | end |
217 | local _ = require('δΈεηΊΏ') | 217 | local _ = require('δΈεηΊΏ') |
218 | local _anon_func_0 = function(_) | 218 | local _anon_func_0 = function(_) |
219 | do | 219 | local _call_0 = (_({ |
220 | local _call_0 = (_({ | 220 | 1, |
221 | 1, | 221 | 2, |
222 | 2, | 222 | 3, |
223 | 3, | 223 | 4, |
224 | 4, | 224 | -2, |
225 | -2, | 225 | 3 |
226 | 3 | 226 | })) |
227 | })) | 227 | return _call_0["ιΎ"](_call_0) |
228 | return _call_0["ιΎ"](_call_0) | ||
229 | end | ||
230 | end | 228 | end |
231 | local _call_0 = ((function() | 229 | local _call_0 = ((function() |
232 | local _call_0 = ((function() | 230 | local _call_0 = ((function() |
@@ -241,17 +239,15 @@ local _call_0 = ((function() | |||
241 | end)()) | 239 | end)()) |
242 | local _u7ed3_u679ca = _call_0["εεΌ"](_call_0) | 240 | local _u7ed3_u679ca = _call_0["εεΌ"](_call_0) |
243 | local _anon_func_1 = function(_) | 241 | local _anon_func_1 = function(_) |
244 | do | 242 | local _call_1 = (_({ |
245 | local _call_1 = (_({ | 243 | 1, |
246 | 1, | 244 | 2, |
247 | 2, | 245 | 3, |
248 | 3, | 246 | 4, |
249 | 4, | 247 | -2, |
250 | -2, | 248 | 3 |
251 | 3 | 249 | })) |
252 | })) | 250 | return _call_1["ιΎ"](_call_1) |
253 | return _call_1["ιΎ"](_call_1) | ||
254 | end | ||
255 | end | 251 | end |
256 | do | 252 | do |
257 | local _call_1 = ((function() | 253 | local _call_1 = ((function() |
@@ -270,10 +266,8 @@ do | |||
270 | end) | 266 | end) |
271 | end | 267 | end |
272 | local _anon_func_2 = function(_u539f_u70b9) | 268 | local _anon_func_2 = function(_u539f_u70b9) |
273 | do | 269 | local _call_1 = _u539f_u70b9["εζ’"]["ζ ΉθηΉ"]["ζΈΈζ对豑"] |
274 | local _call_1 = _u539f_u70b9["εζ’"]["ζ ΉθηΉ"]["ζΈΈζ对豑"] | 270 | return _call_1["ηΆθηΉ"](_call_1) |
275 | return _call_1["ηΆθηΉ"](_call_1) | ||
276 | end | ||
277 | end | 271 | end |
278 | local _call_1 = ((function() | 272 | local _call_1 = ((function() |
279 | local _call_1 = ((function() | 273 | local _call_1 = ((function() |
@@ -365,10 +359,8 @@ local _1 | |||
365 | _1 = function() | 359 | _1 = function() |
366 | _u6253_u5370(1) | 360 | _u6253_u5370(1) |
367 | local _accum_0 = { } | 361 | local _accum_0 = { } |
368 | local _len_0 = 1 | ||
369 | while false do | 362 | while false do |
370 | break | 363 | break |
371 | _len_0 = _len_0 + 1 | ||
372 | end | 364 | end |
373 | return _accum_0 | 365 | return _accum_0 |
374 | end | 366 | end |
diff --git a/spec/outputs/unicode/multiline_chain.lua b/spec/outputs/unicode/multiline_chain.lua index c1da13f..61e7057 100644 --- a/spec/outputs/unicode/multiline_chain.lua +++ b/spec/outputs/unicode/multiline_chain.lua | |||
@@ -59,10 +59,8 @@ _u51fd_u6570 = function() | |||
59 | return _accum_0 | 59 | return _accum_0 |
60 | end | 60 | end |
61 | local _anon_func_0 = function(_u53d8_u91cfa) | 61 | local _anon_func_0 = function(_u53d8_u91cfa) |
62 | do | 62 | local _call_1 = _u53d8_u91cfa |
63 | local _call_1 = _u53d8_u91cfa | 63 | return (_call_1["ειb"](_call_1, 123))["ειc"]("abc") |
64 | return (_call_1["ειb"](_call_1, 123))["ειc"]("abc") | ||
65 | end | ||
66 | end | 64 | end |
67 | local _u51fd_u65701 | 65 | local _u51fd_u65701 |
68 | _u51fd_u65701 = function() | 66 | _u51fd_u65701 = function() |
diff --git a/spec/outputs/unicode/syntax.lua b/spec/outputs/unicode/syntax.lua index 1984f40..a13302b 100644 --- a/spec/outputs/unicode/syntax.lua +++ b/spec/outputs/unicode/syntax.lua | |||
@@ -286,10 +286,8 @@ _ = 5 - _u4ec0_u4e48(_u65e0_u804a) | |||
286 | _u4ec0_u4e48(_u65e0_u804a - 5) | 286 | _u4ec0_u4e48(_u65e0_u804a - 5) |
287 | _u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269 | 287 | _u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269 |
288 | local _anon_func_0 = function(_u4ec0_u4e48) | 288 | local _anon_func_0 = function(_u4ec0_u4e48) |
289 | do | 289 | local _call_8 = _u4ec0_u4e48 |
290 | local _call_8 = _u4ec0_u4e48 | 290 | return _call_8["ι ·"](_call_8, 100) |
291 | return _call_8["ι ·"](_call_8, 100) | ||
292 | end | ||
293 | end | 291 | end |
294 | (function(_u67d0_u7269) | 292 | (function(_u67d0_u7269) |
295 | if _u67d0_u7269 == nil then | 293 | if _u67d0_u7269 == nil then |
diff --git a/spec/outputs/unicode/vararg.lua b/spec/outputs/unicode/vararg.lua index b837006..fc894ff 100644 --- a/spec/outputs/unicode/vararg.lua +++ b/spec/outputs/unicode/vararg.lua | |||
@@ -125,14 +125,10 @@ local _anon_func_11 = function(_u9879_u76ee, ...) | |||
125 | return _tbl_0 | 125 | return _tbl_0 |
126 | end | 126 | end |
127 | local _anon_func_12 = function(_u51fd_u6570) | 127 | local _anon_func_12 = function(_u51fd_u6570) |
128 | do | 128 | return _u51fd_u6570() |
129 | return _u51fd_u6570() | ||
130 | end | ||
131 | end | 129 | end |
132 | local _anon_func_13 = function(_u51fd_u6570, ...) | 130 | local _anon_func_13 = function(_u51fd_u6570, ...) |
133 | do | 131 | return _u51fd_u6570(...) |
134 | return _u51fd_u6570(...) | ||
135 | end | ||
136 | end | 132 | end |
137 | local _anon_func_14 = function(_u51fd_u6570) | 133 | local _anon_func_14 = function(_u51fd_u6570) |
138 | local _accum_0 = { } | 134 | local _accum_0 = { } |
@@ -195,15 +191,11 @@ local _anon_func_23 = function(_u51fd_u6570, ...) | |||
195 | return nil | 191 | return nil |
196 | end | 192 | end |
197 | local _anon_func_24 = function(_u6253_u5370, select, ...) | 193 | local _anon_func_24 = function(_u6253_u5370, select, ...) |
198 | do | 194 | _u6253_u5370(select("#", ...)) |
199 | _u6253_u5370(select("#", ...)) | 195 | return _u6253_u5370(...) |
200 | return _u6253_u5370(...) | ||
201 | end | ||
202 | end | 196 | end |
203 | local _anon_func_25 = function(_u6253_u5370, ...) | 197 | local _anon_func_25 = function(_u6253_u5370, ...) |
204 | do | 198 | return _u6253_u5370(...) |
205 | return _u6253_u5370(...) | ||
206 | end | ||
207 | end | 199 | end |
208 | local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) | 200 | local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) |
209 | if 1 == _u53d8_u91cfx then | 201 | if 1 == _u53d8_u91cfx then |
@@ -214,9 +206,7 @@ local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) | |||
214 | end | 206 | end |
215 | end | 207 | end |
216 | local _anon_func_27 = function(_u6253_u5370, ...) | 208 | local _anon_func_27 = function(_u6253_u5370, ...) |
217 | do | 209 | return _u6253_u5370(...) |
218 | return _u6253_u5370(...) | ||
219 | end | ||
220 | end | 210 | end |
221 | local _anon_func_28 = function(_u6761_u4ef6) | 211 | local _anon_func_28 = function(_u6761_u4ef6) |
222 | if _u6761_u4ef6 then | 212 | if _u6761_u4ef6 then |
@@ -224,10 +214,8 @@ local _anon_func_28 = function(_u6761_u4ef6) | |||
224 | end | 214 | end |
225 | end | 215 | end |
226 | local _anon_func_29 = function(_u6253_u5370, _arg_0, ...) | 216 | local _anon_func_29 = function(_u6253_u5370, _arg_0, ...) |
227 | do | 217 | local _u8868 = _arg_0 |
228 | local _u8868 = _arg_0 | 218 | return _u6253_u5370(...) |
229 | return _u6253_u5370(...) | ||
230 | end | ||
231 | end | 219 | end |
232 | local _u8fde_u63a5 | 220 | local _u8fde_u63a5 |
233 | _u8fde_u63a5 = function(...) | 221 | _u8fde_u63a5 = function(...) |
diff --git a/spec/outputs/upvalue_func.lua b/spec/outputs/upvalue_func.lua index 3181adf..3e088be 100644 --- a/spec/outputs/upvalue_func.lua +++ b/spec/outputs/upvalue_func.lua | |||
@@ -214,10 +214,8 @@ local _anon_func_1 = function(valueB) | |||
214 | end | 214 | end |
215 | end | 215 | end |
216 | local _anon_func_2 = function(print, select, _arg_0, ...) | 216 | local _anon_func_2 = function(print, select, _arg_0, ...) |
217 | do | 217 | local ok = _arg_0 |
218 | local ok = _arg_0 | 218 | return print(select(3, ...)) |
219 | return print(select(3, ...)) | ||
220 | end | ||
221 | end | 219 | end |
222 | local _anon_func_3 = function(tb) | 220 | local _anon_func_3 = function(tb) |
223 | if tb ~= nil then | 221 | if tb ~= nil then |
@@ -242,11 +240,9 @@ local _anon_func_5 = function(getmetatable, tb) | |||
242 | return _obj_0[1 + 1](_obj_0, "abc") | 240 | return _obj_0[1 + 1](_obj_0, "abc") |
243 | end | 241 | end |
244 | local _anon_func_6 = function(tb) | 242 | local _anon_func_6 = function(tb) |
245 | do | 243 | local _call_0 = tb |
246 | local _call_0 = tb | 244 | local _call_1 = _call_0["end"](_call_0) |
247 | local _call_1 = _call_0["end"](_call_0) | 245 | return _call_1["π€£"](_call_1, 123) |
248 | return _call_1["π€£"](_call_1, 123) | ||
249 | end | ||
250 | end | 246 | end |
251 | local _anon_func_7 = function(itemA, listA) | 247 | local _anon_func_7 = function(itemA, listA) |
252 | for _index_0 = 1, #listA do | 248 | for _index_0 = 1, #listA do |
@@ -354,17 +350,13 @@ local _anon_func_16 = function(pairs, tb, tostring) | |||
354 | return _tbl_0 | 350 | return _tbl_0 |
355 | end | 351 | end |
356 | local _anon_func_17 = function(print) | 352 | local _anon_func_17 = function(print) |
357 | do | 353 | print(123) |
358 | print(123) | 354 | return "abc" |
359 | return "abc" | ||
360 | end | ||
361 | end | 355 | end |
362 | local _anon_func_18 = function(print, select, _arg_0, ...) | 356 | local _anon_func_18 = function(print, select, _arg_0, ...) |
363 | do | 357 | local success = _arg_0 |
364 | local success = _arg_0 | 358 | if success then |
365 | if success then | 359 | return print(select('#', ...)) |
366 | return print(select('#', ...)) | ||
367 | end | ||
368 | end | 360 | end |
369 | end | 361 | end |
370 | local _anon_func_19 = function(cond, i) | 362 | local _anon_func_19 = function(cond, i) |
@@ -459,11 +451,9 @@ local _anon_func_25 = function(itemA, listA) | |||
459 | return false | 451 | return false |
460 | end | 452 | end |
461 | local _anon_func_24 = function(itemA, listA, tb) | 453 | local _anon_func_24 = function(itemA, listA, tb) |
462 | do | 454 | local _call_0 = tb |
463 | local _call_0 = tb | 455 | local _call_1 = _call_0["end"](_call_0) |
464 | local _call_1 = _call_0["end"](_call_0) | 456 | return _call_1["π€£"](_call_1, 123 and (#listA > 0 and _anon_func_25(itemA, listA))) |
465 | return _call_1["π€£"](_call_1, 123 and (#listA > 0 and _anon_func_25(itemA, listA))) | ||
466 | end | ||
467 | end | 457 | end |
468 | GameEngine:onEvent("SomeEvent", function() | 458 | GameEngine:onEvent("SomeEvent", function() |
469 | return func(value + (_anon_func_21(cond)) + (_anon_func_22(valueB)) > _anon_func_23(tb) + _anon_func_24(itemA, listA, tb)) | 459 | return func(value + (_anon_func_21(cond)) + (_anon_func_22(valueB)) > _anon_func_23(tb) + _anon_func_24(itemA, listA, tb)) |
@@ -503,13 +493,11 @@ local _anon_func_27 = function(char) | |||
503 | return nil | 493 | return nil |
504 | end | 494 | end |
505 | local _anon_func_28 = function(os, _arg_0, ...) | 495 | local _anon_func_28 = function(os, _arg_0, ...) |
506 | do | 496 | local ok = _arg_0 |
507 | local ok = _arg_0 | 497 | if ok then |
508 | if ok then | 498 | return ... |
509 | return ... | 499 | else |
510 | else | 500 | return os.exit(1) |
511 | return os.exit(1) | ||
512 | end | ||
513 | end | 501 | end |
514 | end | 502 | end |
515 | local _anon_func_29 = function(debug_env_after, debug_env_before, env, func) | 503 | local _anon_func_29 = function(debug_env_after, debug_env_before, env, func) |
diff --git a/spec/outputs/vararg.lua b/spec/outputs/vararg.lua index dabba44..254aa6a 100644 --- a/spec/outputs/vararg.lua +++ b/spec/outputs/vararg.lua | |||
@@ -125,14 +125,10 @@ local _anon_func_11 = function(items, ...) | |||
125 | return _tbl_0 | 125 | return _tbl_0 |
126 | end | 126 | end |
127 | local _anon_func_12 = function(func) | 127 | local _anon_func_12 = function(func) |
128 | do | 128 | return func() |
129 | return func() | ||
130 | end | ||
131 | end | 129 | end |
132 | local _anon_func_13 = function(func, ...) | 130 | local _anon_func_13 = function(func, ...) |
133 | do | 131 | return func(...) |
134 | return func(...) | ||
135 | end | ||
136 | end | 132 | end |
137 | local _anon_func_14 = function(func) | 133 | local _anon_func_14 = function(func) |
138 | local _accum_0 = { } | 134 | local _accum_0 = { } |
@@ -195,15 +191,11 @@ local _anon_func_23 = function(func, ...) | |||
195 | return nil | 191 | return nil |
196 | end | 192 | end |
197 | local _anon_func_24 = function(print, select, ...) | 193 | local _anon_func_24 = function(print, select, ...) |
198 | do | 194 | print(select("#", ...)) |
199 | print(select("#", ...)) | 195 | return print(...) |
200 | return print(...) | ||
201 | end | ||
202 | end | 196 | end |
203 | local _anon_func_25 = function(print, ...) | 197 | local _anon_func_25 = function(print, ...) |
204 | do | 198 | return print(...) |
205 | return print(...) | ||
206 | end | ||
207 | end | 199 | end |
208 | local _anon_func_26 = function(tb, tb2, x) | 200 | local _anon_func_26 = function(tb, tb2, x) |
209 | if 1 == x then | 201 | if 1 == x then |
@@ -214,9 +206,7 @@ local _anon_func_26 = function(tb, tb2, x) | |||
214 | end | 206 | end |
215 | end | 207 | end |
216 | local _anon_func_27 = function(print, ...) | 208 | local _anon_func_27 = function(print, ...) |
217 | do | 209 | return print(...) |
218 | return print(...) | ||
219 | end | ||
220 | end | 210 | end |
221 | local _anon_func_28 = function(cond) | 211 | local _anon_func_28 = function(cond) |
222 | if cond then | 212 | if cond then |
@@ -224,10 +214,8 @@ local _anon_func_28 = function(cond) | |||
224 | end | 214 | end |
225 | end | 215 | end |
226 | local _anon_func_29 = function(print, _arg_0, ...) | 216 | local _anon_func_29 = function(print, _arg_0, ...) |
227 | do | 217 | local tb = _arg_0 |
228 | local tb = _arg_0 | 218 | return print(...) |
229 | return print(...) | ||
230 | end | ||
231 | end | 219 | end |
232 | local join | 220 | local join |
233 | join = function(...) | 221 | join = function(...) |
diff --git a/spec/outputs/with.lua b/spec/outputs/with.lua index 1a795c1..530915e 100644 --- a/spec/outputs/with.lua +++ b/spec/outputs/with.lua | |||
@@ -187,4 +187,66 @@ do | |||
187 | return _with_0[123] | 187 | return _with_0[123] |
188 | end | 188 | end |
189 | end | 189 | end |
190 | do | ||
191 | f((function() | ||
192 | local _with_0 = item | ||
193 | do | ||
194 | local _accum_0 | ||
195 | repeat | ||
196 | if _with_0.id > 0 then | ||
197 | _accum_0 = _with_0.content | ||
198 | break | ||
199 | end | ||
200 | until true | ||
201 | _with_0 = _accum_0 | ||
202 | end | ||
203 | return _with_0 | ||
204 | end)()) | ||
205 | local a | ||
206 | do | ||
207 | local _with_0 = tb | ||
208 | do | ||
209 | local _accum_0 | ||
210 | repeat | ||
211 | if _with_0.v then | ||
212 | _accum_0 = _with_0.a | ||
213 | break | ||
214 | end | ||
215 | until true | ||
216 | _with_0 = _accum_0 | ||
217 | end | ||
218 | a = _with_0 | ||
219 | end | ||
220 | local _accum_0 | ||
221 | while true do | ||
222 | local _with_0 = tb | ||
223 | local _accum_1 | ||
224 | repeat | ||
225 | if _with_0 ~= nil then | ||
226 | _accum_1 = 1 | ||
227 | break | ||
228 | end | ||
229 | until true | ||
230 | _with_0 = _accum_1 | ||
231 | _accum_0 = _with_0 | ||
232 | break | ||
233 | end | ||
234 | a = _accum_0 | ||
235 | end | ||
236 | do | ||
237 | local a | ||
238 | local _accum_0 | ||
239 | for i = 1, 100 do | ||
240 | local x = tb[i] | ||
241 | if x ~= nil then | ||
242 | local _des_0 = 1 | ||
243 | if _des_0 then | ||
244 | x.id = _des_0 | ||
245 | _accum_0 = x | ||
246 | break | ||
247 | end | ||
248 | end | ||
249 | end | ||
250 | a = _accum_0 | ||
251 | end | ||
190 | return nil | 252 | return nil |
diff --git a/src/3rdParty/efsw/FileWatcherGeneric.cpp b/src/3rdParty/efsw/FileWatcherGeneric.cpp index 3f3c52e..468d27c 100644 --- a/src/3rdParty/efsw/FileWatcherGeneric.cpp +++ b/src/3rdParty/efsw/FileWatcherGeneric.cpp | |||
@@ -25,7 +25,7 @@ FileWatcherGeneric::~FileWatcherGeneric() { | |||
25 | } | 25 | } |
26 | 26 | ||
27 | WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, | 27 | WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, |
28 | bool recursive, const std::vector<WatcherOption>& options ) { | 28 | bool recursive, const std::vector<WatcherOption>& /*options*/ ) { |
29 | std::string dir( directory ); | 29 | std::string dir( directory ); |
30 | 30 | ||
31 | FileSystem::dirAddSlashAtEnd( dir ); | 31 | FileSystem::dirAddSlashAtEnd( dir ); |
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index fe6e726..945e1d7 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
@@ -167,12 +167,11 @@ std::string ExistentialOp_t::to_string(void*) const { | |||
167 | std::string TableAppendingOp_t::to_string(void*) const { | 167 | std::string TableAppendingOp_t::to_string(void*) const { |
168 | return "[]"s; | 168 | return "[]"s; |
169 | } | 169 | } |
170 | std::string PlainItem_t::to_string(void *) const { | 170 | std::string PlainItem_t::to_string(void*) const { |
171 | return {}; | 171 | return {}; |
172 | } | 172 | } |
173 | std::string GlobalOp_t::to_string(void* ud) const { | 173 | std::string GlobalOp_t::to_string(void*) const { |
174 | auto info = reinterpret_cast<YueFormat*>(ud); | 174 | return "*"s; |
175 | return info->convert(this); | ||
176 | } | 175 | } |
177 | std::string ExportDefault_t::to_string(void*) const { | 176 | std::string ExportDefault_t::to_string(void*) const { |
178 | return "default"s; | 177 | return "default"s; |
@@ -188,9 +187,17 @@ std::string ConstValue_t::to_string(void* ud) const { | |||
188 | std::string NotIn_t::to_string(void*) const { | 187 | std::string NotIn_t::to_string(void*) const { |
189 | return {}; | 188 | return {}; |
190 | } | 189 | } |
190 | std::string Break_t::to_string(void*) const { | ||
191 | return "break"s; | ||
192 | } | ||
193 | std::string Continue_t::to_string(void*) const { | ||
194 | return "continue"s; | ||
195 | } | ||
191 | std::string BreakLoop_t::to_string(void* ud) const { | 196 | std::string BreakLoop_t::to_string(void* ud) const { |
192 | auto info = reinterpret_cast<YueFormat*>(ud); | 197 | if (value) { |
193 | return info->convert(this); | 198 | return type->to_string(ud) + ' ' + value->to_string(ud); |
199 | } | ||
200 | return type->to_string(ud); | ||
194 | } | 201 | } |
195 | std::string YueLineComment_t::to_string(void* ud) const { | 202 | std::string YueLineComment_t::to_string(void* ud) const { |
196 | auto info = reinterpret_cast<YueFormat*>(ud); | 203 | auto info = reinterpret_cast<YueFormat*>(ud); |
@@ -297,6 +304,17 @@ std::string ImportAs_t::to_string(void* ud) const { | |||
297 | } | 304 | } |
298 | return join(temp, " "s); | 305 | return join(temp, " "s); |
299 | } | 306 | } |
307 | std::string ImportGlobal_t::to_string(void* ud) const { | ||
308 | str_list temp; | ||
309 | for (auto seg : segs.objects()) { | ||
310 | temp.emplace_back(seg->to_string(ud)); | ||
311 | } | ||
312 | auto item = join(temp, "."s); | ||
313 | if (target) { | ||
314 | return item + " as "s + target->to_string(ud); | ||
315 | } | ||
316 | return item; | ||
317 | } | ||
300 | std::string Import_t::to_string(void* ud) const { | 318 | std::string Import_t::to_string(void* ud) const { |
301 | if (ast_is<FromImport_t>(content)) { | 319 | if (ast_is<FromImport_t>(content)) { |
302 | return content->to_string(ud); | 320 | return content->to_string(ud); |
@@ -324,6 +342,12 @@ std::string Backcall_t::to_string(void* ud) const { | |||
324 | temp.emplace_back(value->to_string(ud)); | 342 | temp.emplace_back(value->to_string(ud)); |
325 | return join(temp, " "sv); | 343 | return join(temp, " "sv); |
326 | } | 344 | } |
345 | std::string SubBackcall_t::to_string(void* ud) const { | ||
346 | str_list temp; | ||
347 | temp.emplace_back(arrow->to_string(ud)); | ||
348 | temp.emplace_back(value->to_string(ud)); | ||
349 | return join(temp, " "sv); | ||
350 | } | ||
327 | std::string PipeBody_t::to_string(void* ud) const { | 351 | std::string PipeBody_t::to_string(void* ud) const { |
328 | auto info = reinterpret_cast<YueFormat*>(ud); | 352 | auto info = reinterpret_cast<YueFormat*>(ud); |
329 | str_list temp; | 353 | str_list temp; |
@@ -359,8 +383,8 @@ std::string With_t::to_string(void* ud) const { | |||
359 | str_list temp{ | 383 | str_list temp{ |
360 | eop ? "with?"s : "with"s, | 384 | eop ? "with?"s : "with"s, |
361 | valueList->to_string(ud)}; | 385 | valueList->to_string(ud)}; |
362 | if (assigns) { | 386 | if (assign) { |
363 | temp.push_back(assigns->to_string(ud)); | 387 | temp.push_back(':' + assign->to_string(ud)); |
364 | } | 388 | } |
365 | if (body.is<Statement_t>()) { | 389 | if (body.is<Statement_t>()) { |
366 | return join(temp, " "sv) + " do "s + body->to_string(ud); | 390 | return join(temp, " "sv) + " do "s + body->to_string(ud); |
@@ -406,6 +430,9 @@ std::string SwitchCase_t::to_string(void* ud) const { | |||
406 | std::string Switch_t::to_string(void* ud) const { | 430 | std::string Switch_t::to_string(void* ud) const { |
407 | auto info = reinterpret_cast<YueFormat*>(ud); | 431 | auto info = reinterpret_cast<YueFormat*>(ud); |
408 | str_list temp{"switch "s + target->to_string(ud)}; | 432 | str_list temp{"switch "s + target->to_string(ud)}; |
433 | if (assignment) { | ||
434 | temp.back().append(assignment->to_string(ud)); | ||
435 | } | ||
409 | info->pushScope(); | 436 | info->pushScope(); |
410 | for (auto branch : branches.objects()) { | 437 | for (auto branch : branches.objects()) { |
411 | temp.emplace_back(info->ind() + branch->to_string(ud)); | 438 | temp.emplace_back(info->ind() + branch->to_string(ud)); |
@@ -449,41 +476,75 @@ std::string If_t::to_string(void* ud) const { | |||
449 | temp.back() += " then"s; | 476 | temp.back() += " then"s; |
450 | } | 477 | } |
451 | ++it; | 478 | ++it; |
452 | bool condition = true; | 479 | enum class NType { |
480 | Cond, | ||
481 | Stat, | ||
482 | Block | ||
483 | }; | ||
484 | NType lastType = NType::Cond; | ||
453 | for (; it != nodes.objects().end(); ++it) { | 485 | for (; it != nodes.objects().end(); ++it) { |
454 | auto node = *it; | 486 | auto node = *it; |
455 | switch (node->get_id()) { | 487 | switch (node->get_id()) { |
456 | case id<IfCond_t>(): | 488 | case id<IfCond_t>(): |
457 | temp.emplace_back(info->ind() + "elseif "s + node->to_string(ud)); | 489 | temp.emplace_back(info->ind() + "elseif "s + node->to_string(ud)); |
458 | condition = true; | 490 | lastType = NType::Cond; |
459 | break; | 491 | break; |
460 | case id<Statement_t>(): { | 492 | case id<Statement_t>(): { |
461 | if (condition) { | 493 | switch (lastType) { |
462 | temp.back() += " then "s + node->to_string(ud); | 494 | case NType::Cond: |
463 | } else { | 495 | temp.back() += " then "s + node->to_string(ud); |
464 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | 496 | break; |
497 | case NType::Stat: | ||
498 | if (temp.back().back() == '\n') { | ||
499 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | ||
500 | } else { | ||
501 | temp.back() += " else "s + node->to_string(ud); | ||
502 | } | ||
503 | break; | ||
504 | case NType::Block: | ||
505 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | ||
506 | break; | ||
465 | } | 507 | } |
466 | condition = false; | 508 | lastType = NType::Stat; |
467 | break; | 509 | break; |
468 | } | 510 | } |
469 | case id<Block_t>(): { | 511 | case id<Block_t>(): { |
470 | if (condition) { | 512 | switch (lastType) { |
471 | info->pushScope(); | 513 | case NType::Cond: { |
472 | temp.emplace_back(node->to_string(ud)); | 514 | info->pushScope(); |
473 | if (temp.back().empty()) { | 515 | temp.emplace_back(node->to_string(ud)); |
474 | temp.back() = info->ind() + "--"s; | 516 | if (temp.back().empty()) { |
517 | temp.back() = info->ind() + "--"s; | ||
518 | } | ||
519 | info->popScope(); | ||
520 | break; | ||
521 | } | ||
522 | case NType::Stat: { | ||
523 | if (temp.back().back() == '\n') { | ||
524 | temp.emplace_back(info->ind() + "else"s); | ||
525 | } else { | ||
526 | temp.back() += " else"s; | ||
527 | } | ||
528 | info->pushScope(); | ||
529 | temp.emplace_back(node->to_string(ud)); | ||
530 | if (temp.back().empty()) { | ||
531 | temp.back() = info->ind() + "--"s; | ||
532 | } | ||
533 | info->popScope(); | ||
534 | break; | ||
475 | } | 535 | } |
476 | info->popScope(); | 536 | case NType::Block: { |
477 | } else { | 537 | temp.emplace_back(info->ind() + "else"s); |
478 | temp.emplace_back(info->ind() + "else"s); | 538 | info->pushScope(); |
479 | info->pushScope(); | 539 | temp.emplace_back(node->to_string(ud)); |
480 | temp.emplace_back(node->to_string(ud)); | 540 | if (temp.back().empty()) { |
481 | if (temp.back().empty()) { | 541 | temp.back() = info->ind() + "--"s; |
482 | temp.back() = info->ind() + "--"s; | 542 | } |
543 | info->popScope(); | ||
544 | break; | ||
483 | } | 545 | } |
484 | info->popScope(); | ||
485 | } | 546 | } |
486 | condition = false; | 547 | lastType = NType::Block; |
487 | break; | 548 | break; |
488 | } | 549 | } |
489 | } | 550 | } |
@@ -511,10 +572,10 @@ std::string While_t::to_string(void* ud) const { | |||
511 | } | 572 | } |
512 | std::string Repeat_t::to_string(void* ud) const { | 573 | std::string Repeat_t::to_string(void* ud) const { |
513 | auto info = reinterpret_cast<YueFormat*>(ud); | 574 | auto info = reinterpret_cast<YueFormat*>(ud); |
514 | str_list temp; | 575 | if (body.is<Statement_t>()) { |
515 | if (body->content.is<Statement_t>()) { | 576 | return "repeat "s + body->to_string(ud) + " until "s + condition->to_string(ud); |
516 | temp.emplace_back("repeat "s + body->to_string(ud)); | ||
517 | } else { | 577 | } else { |
578 | str_list temp; | ||
518 | temp.emplace_back("repeat"s); | 579 | temp.emplace_back("repeat"s); |
519 | info->pushScope(); | 580 | info->pushScope(); |
520 | temp.emplace_back(body->to_string(ud)); | 581 | temp.emplace_back(body->to_string(ud)); |
@@ -522,9 +583,9 @@ std::string Repeat_t::to_string(void* ud) const { | |||
522 | temp.back() = info->ind() + "--"s; | 583 | temp.back() = info->ind() + "--"s; |
523 | } | 584 | } |
524 | info->popScope(); | 585 | info->popScope(); |
586 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
587 | return join(temp, "\n"sv); | ||
525 | } | 588 | } |
526 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
527 | return join(temp, "\n"sv); | ||
528 | } | 589 | } |
529 | std::string ForStepValue_t::to_string(void* ud) const { | 590 | std::string ForStepValue_t::to_string(void* ud) const { |
530 | return value->to_string(ud); | 591 | return value->to_string(ud); |
@@ -596,10 +657,13 @@ std::string CatchBlock_t::to_string(void* ud) const { | |||
596 | std::string Try_t::to_string(void* ud) const { | 657 | std::string Try_t::to_string(void* ud) const { |
597 | auto info = reinterpret_cast<YueFormat*>(ud); | 658 | auto info = reinterpret_cast<YueFormat*>(ud); |
598 | str_list temp; | 659 | str_list temp; |
660 | temp.emplace_back("try"s); | ||
661 | if (eop) { | ||
662 | temp.back() += eop->to_string(ud); | ||
663 | } | ||
599 | if (func.is<Exp_t>()) { | 664 | if (func.is<Exp_t>()) { |
600 | temp.emplace_back("try "s + func->to_string(ud)); | 665 | temp.back() += (" "s + func->to_string(ud)); |
601 | } else { | 666 | } else { |
602 | temp.emplace_back("try"s); | ||
603 | info->pushScope(); | 667 | info->pushScope(); |
604 | temp.emplace_back(func->to_string(ud)); | 668 | temp.emplace_back(func->to_string(ud)); |
605 | if (temp.back().empty()) { | 669 | if (temp.back().empty()) { |
@@ -851,6 +915,12 @@ std::string Exp_t::to_string(void* ud) const { | |||
851 | } | 915 | } |
852 | return join(temp, " "sv); | 916 | return join(temp, " "sv); |
853 | } | 917 | } |
918 | std::string ReversedIndex_t::to_string(void* ud) const { | ||
919 | if (modifier) { | ||
920 | return "[# - "s + modifier->to_string(ud) + ']'; | ||
921 | } | ||
922 | return "[#]"s; | ||
923 | } | ||
854 | std::string Callable_t::to_string(void* ud) const { | 924 | std::string Callable_t::to_string(void* ud) const { |
855 | return item->to_string(ud); | 925 | return item->to_string(ud); |
856 | } | 926 | } |
@@ -937,6 +1007,51 @@ std::string DoubleString_t::to_string(void* ud) const { | |||
937 | } | 1007 | } |
938 | return '"' + join(temp) + '"'; | 1008 | return '"' + join(temp) + '"'; |
939 | } | 1009 | } |
1010 | std::string YAMLIndent_t::to_string(void* ud) const { | ||
1011 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
1012 | return info->convert(this); | ||
1013 | } | ||
1014 | std::string YAMLLineInner_t::to_string(void* ud) const { | ||
1015 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
1016 | return info->convert(this); | ||
1017 | } | ||
1018 | std::string YAMLLineContent_t::to_string(void* ud) const { | ||
1019 | if (content.is<Exp_t>()) { | ||
1020 | return "#{"s + content->to_string(ud) + '}'; | ||
1021 | } | ||
1022 | return content->to_string(ud); | ||
1023 | } | ||
1024 | std::string YAMLLine_t::to_string(void* ud) const { | ||
1025 | str_list temp; | ||
1026 | for (auto seg : segments.objects()) { | ||
1027 | temp.emplace_back(seg->to_string(ud)); | ||
1028 | } | ||
1029 | return join(temp); | ||
1030 | } | ||
1031 | std::string YAMLMultiline_t::to_string(void* ud) const { | ||
1032 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
1033 | int currentIndent = info->indent; | ||
1034 | str_list temp; | ||
1035 | int lastIndent = -1; | ||
1036 | for (auto line_ : lines.objects()) { | ||
1037 | auto line = static_cast<YAMLLine_t*>(line_); | ||
1038 | auto indent = line->indent->to_string(ud); | ||
1039 | int ind = 0; | ||
1040 | for (auto c : indent) { | ||
1041 | if (c == ' ') ind++; | ||
1042 | if (c == '\t') ind += 4; | ||
1043 | } | ||
1044 | if (lastIndent < ind) { | ||
1045 | info->pushScope(); | ||
1046 | } else if (lastIndent > ind) { | ||
1047 | info->popScope(); | ||
1048 | } | ||
1049 | lastIndent = ind; | ||
1050 | temp.emplace_back(indent + line->to_string(ud)); | ||
1051 | } | ||
1052 | info->indent = currentIndent; | ||
1053 | return "|\n" + join(temp, "\n"sv) + '\n'; | ||
1054 | } | ||
940 | std::string String_t::to_string(void* ud) const { | 1055 | std::string String_t::to_string(void* ud) const { |
941 | return str->to_string(ud); | 1056 | return str->to_string(ud); |
942 | } | 1057 | } |
@@ -1125,7 +1240,7 @@ std::string ClassDecl_t::to_string(void* ud) const { | |||
1125 | return line; | 1240 | return line; |
1126 | } | 1241 | } |
1127 | std::string GlobalValues_t::to_string(void* ud) const { | 1242 | std::string GlobalValues_t::to_string(void* ud) const { |
1128 | auto line = nameList->to_string(ud); | 1243 | std::string line = nameList->to_string(ud); |
1129 | if (valueList) { | 1244 | if (valueList) { |
1130 | if (valueList.is<TableBlock_t>()) { | 1245 | if (valueList.is<TableBlock_t>()) { |
1131 | line += " =\n"s + valueList->to_string(ud); | 1246 | line += " =\n"s + valueList->to_string(ud); |
@@ -1136,7 +1251,7 @@ std::string GlobalValues_t::to_string(void* ud) const { | |||
1136 | return line; | 1251 | return line; |
1137 | } | 1252 | } |
1138 | std::string Global_t::to_string(void* ud) const { | 1253 | std::string Global_t::to_string(void* ud) const { |
1139 | return "global "s + item->to_string(ud); | 1254 | return "global "s + (constAttrib ? "const "s : ""s) + item->to_string(ud); |
1140 | } | 1255 | } |
1141 | std::string Export_t::to_string(void* ud) const { | 1256 | std::string Export_t::to_string(void* ud) const { |
1142 | auto line = "export"s; | 1257 | auto line = "export"s; |
@@ -1235,6 +1350,9 @@ std::string FnArgDef_t::to_string(void* ud) const { | |||
1235 | if (op) { | 1350 | if (op) { |
1236 | line += op->to_string(ud); | 1351 | line += op->to_string(ud); |
1237 | } | 1352 | } |
1353 | if (label) { | ||
1354 | line += '`' + label->to_string(ud); | ||
1355 | } | ||
1238 | if (defaultValue) { | 1356 | if (defaultValue) { |
1239 | line += " = "s + defaultValue->to_string(ud); | 1357 | line += " = "s + defaultValue->to_string(ud); |
1240 | } | 1358 | } |
@@ -1257,6 +1375,9 @@ std::string FnArgDefList_t::to_string(void* ud) const { | |||
1257 | } | 1375 | } |
1258 | if (varArg) { | 1376 | if (varArg) { |
1259 | temp.emplace_back(info->ind() + varArg->to_string(ud)); | 1377 | temp.emplace_back(info->ind() + varArg->to_string(ud)); |
1378 | if (label) { | ||
1379 | temp.back().append('`' + label->to_string(ud)); | ||
1380 | } | ||
1260 | } | 1381 | } |
1261 | return join(temp, "\n"sv); | 1382 | return join(temp, "\n"sv); |
1262 | } else { | 1383 | } else { |
@@ -1265,6 +1386,9 @@ std::string FnArgDefList_t::to_string(void* ud) const { | |||
1265 | } | 1386 | } |
1266 | if (varArg) { | 1387 | if (varArg) { |
1267 | temp.emplace_back(varArg->to_string(ud)); | 1388 | temp.emplace_back(varArg->to_string(ud)); |
1389 | if (label) { | ||
1390 | temp.back().append('`' + label->to_string(ud)); | ||
1391 | } | ||
1268 | } | 1392 | } |
1269 | return join(temp, ", "sv); | 1393 | return join(temp, ", "sv); |
1270 | } | 1394 | } |
@@ -1546,3 +1670,4 @@ std::string File_t::to_string(void* ud) const { | |||
1546 | } // namespace yue | 1670 | } // namespace yue |
1547 | 1671 | ||
1548 | } // namespace parserlib | 1672 | } // namespace parserlib |
1673 | |||
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 5e70645..1937eb8 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -233,8 +233,15 @@ AST_NODE(ImportAs) | |||
233 | AST_MEMBER(ImportAs, &literal, &target) | 233 | AST_MEMBER(ImportAs, &literal, &target) |
234 | AST_END(ImportAs) | 234 | AST_END(ImportAs) |
235 | 235 | ||
236 | AST_NODE(ImportGlobal) | ||
237 | ast_ptr<true, Seperator_t> sep; | ||
238 | ast_list<true, UnicodeName_t> segs; | ||
239 | ast_ptr<false, Variable_t> target; | ||
240 | AST_MEMBER(ImportGlobal, &sep, &segs, &target) | ||
241 | AST_END(ImportGlobal) | ||
242 | |||
236 | AST_NODE(Import) | 243 | AST_NODE(Import) |
237 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t> content; | 244 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t, ImportGlobal_t> content; |
238 | AST_MEMBER(Import, &content) | 245 | AST_MEMBER(Import, &content) |
239 | AST_END(Import) | 246 | AST_END(Import) |
240 | 247 | ||
@@ -273,6 +280,8 @@ AST_NODE(ExpList) | |||
273 | ast_ptr<true, Seperator_t> sep; | 280 | ast_ptr<true, Seperator_t> sep; |
274 | ast_list<true, Exp_t> exprs; | 281 | ast_list<true, Exp_t> exprs; |
275 | AST_MEMBER(ExpList, &sep, &exprs) | 282 | AST_MEMBER(ExpList, &sep, &exprs) |
283 | bool followStmtProcessed = false; | ||
284 | Statement_t* followStmt = nullptr; | ||
276 | AST_END(ExpList) | 285 | AST_END(ExpList) |
277 | 286 | ||
278 | AST_NODE(Return) | 287 | AST_NODE(Return) |
@@ -285,9 +294,9 @@ AST_END(Return) | |||
285 | AST_NODE(With) | 294 | AST_NODE(With) |
286 | ast_ptr<false, ExistentialOp_t> eop; | 295 | ast_ptr<false, ExistentialOp_t> eop; |
287 | ast_ptr<true, ExpList_t> valueList; | 296 | ast_ptr<true, ExpList_t> valueList; |
288 | ast_ptr<false, Assign_t> assigns; | 297 | ast_ptr<false, Assign_t> assign; |
289 | ast_sel<true, Block_t, Statement_t> body; | 298 | ast_sel<true, Block_t, Statement_t> body; |
290 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) | 299 | AST_MEMBER(With, &eop, &valueList, &assign, &body) |
291 | AST_END(With) | 300 | AST_END(With) |
292 | 301 | ||
293 | AST_NODE(SwitchList) | 302 | AST_NODE(SwitchList) |
@@ -302,20 +311,21 @@ AST_NODE(SwitchCase) | |||
302 | AST_MEMBER(SwitchCase, &condition, &body) | 311 | AST_MEMBER(SwitchCase, &condition, &body) |
303 | AST_END(SwitchCase) | 312 | AST_END(SwitchCase) |
304 | 313 | ||
314 | AST_NODE(Assignment) | ||
315 | ast_ptr<false, ExpList_t> expList; | ||
316 | ast_ptr<true, Assign_t> assign; | ||
317 | AST_MEMBER(Assignment, &expList, &assign) | ||
318 | AST_END(Assignment) | ||
319 | |||
305 | AST_NODE(Switch) | 320 | AST_NODE(Switch) |
306 | ast_ptr<true, Exp_t> target; | 321 | ast_ptr<true, Exp_t> target; |
322 | ast_ptr<false, Assignment_t> assignment; | ||
307 | ast_ptr<true, Seperator_t> sep; | 323 | ast_ptr<true, Seperator_t> sep; |
308 | ast_list<true, SwitchCase_t> branches; | 324 | ast_list<true, SwitchCase_t> branches; |
309 | ast_sel<false, Block_t, Statement_t> lastBranch; | 325 | ast_sel<false, Block_t, Statement_t> lastBranch; |
310 | AST_MEMBER(Switch, &target, &sep, &branches, &lastBranch) | 326 | AST_MEMBER(Switch, &target, &assignment, &sep, &branches, &lastBranch) |
311 | AST_END(Switch) | 327 | AST_END(Switch) |
312 | 328 | ||
313 | AST_NODE(Assignment) | ||
314 | ast_ptr<false, ExpList_t> expList; | ||
315 | ast_ptr<true, Assign_t> assign; | ||
316 | AST_MEMBER(Assignment, &expList, &assign) | ||
317 | AST_END(Assignment) | ||
318 | |||
319 | AST_NODE(IfCond) | 329 | AST_NODE(IfCond) |
320 | ast_ptr<true, Exp_t> condition; | 330 | ast_ptr<true, Exp_t> condition; |
321 | ast_ptr<false, Assignment_t> assignment; | 331 | ast_ptr<false, Assignment_t> assignment; |
@@ -343,7 +353,7 @@ AST_NODE(While) | |||
343 | AST_END(While) | 353 | AST_END(While) |
344 | 354 | ||
345 | AST_NODE(Repeat) | 355 | AST_NODE(Repeat) |
346 | ast_ptr<true, Body_t> body; | 356 | ast_sel<true, Block_t, Statement_t> body; |
347 | ast_ptr<true, Exp_t> condition; | 357 | ast_ptr<true, Exp_t> condition; |
348 | AST_MEMBER(Repeat, &body, &condition) | 358 | AST_MEMBER(Repeat, &body, &condition) |
349 | AST_END(Repeat) | 359 | AST_END(Repeat) |
@@ -381,9 +391,10 @@ AST_NODE(CatchBlock) | |||
381 | AST_END(CatchBlock) | 391 | AST_END(CatchBlock) |
382 | 392 | ||
383 | AST_NODE(Try) | 393 | AST_NODE(Try) |
394 | ast_ptr<false, ExistentialOp_t> eop; | ||
384 | ast_sel<true, Block_t, Exp_t> func; | 395 | ast_sel<true, Block_t, Exp_t> func; |
385 | ast_ptr<false, CatchBlock_t> catchBlock; | 396 | ast_ptr<false, CatchBlock_t> catchBlock; |
386 | AST_MEMBER(Try, &func, &catchBlock) | 397 | AST_MEMBER(Try, &eop, &func, &catchBlock) |
387 | AST_END(Try) | 398 | AST_END(Try) |
388 | 399 | ||
389 | AST_NODE(Comprehension) | 400 | AST_NODE(Comprehension) |
@@ -547,8 +558,8 @@ AST_NODE(SimpleValue) | |||
547 | ast_sel<true, | 558 | ast_sel<true, |
548 | TableLit_t, ConstValue_t, | 559 | TableLit_t, ConstValue_t, |
549 | If_t, Switch_t, With_t, ClassDecl_t, | 560 | If_t, Switch_t, With_t, ClassDecl_t, |
550 | ForEach_t, For_t, While_t, Do_t, Try_t, | 561 | ForEach_t, For_t, While_t, Repeat_t, |
551 | UnaryValue_t, | 562 | Do_t, Try_t, UnaryValue_t, |
552 | TblComprehension_t, Comprehension_t, | 563 | TblComprehension_t, Comprehension_t, |
553 | FunLit_t, Num_t, VarArg_t> value; | 564 | FunLit_t, Num_t, VarArg_t> value; |
554 | AST_MEMBER(SimpleValue, &value) | 565 | AST_MEMBER(SimpleValue, &value) |
@@ -587,8 +598,31 @@ AST_NODE(DoubleString) | |||
587 | AST_MEMBER(DoubleString, &sep, &segments) | 598 | AST_MEMBER(DoubleString, &sep, &segments) |
588 | AST_END(DoubleString) | 599 | AST_END(DoubleString) |
589 | 600 | ||
601 | AST_LEAF(YAMLIndent) | ||
602 | AST_END(YAMLIndent) | ||
603 | |||
604 | AST_LEAF(YAMLLineInner) | ||
605 | AST_END(YAMLLineInner) | ||
606 | |||
607 | AST_NODE(YAMLLineContent) | ||
608 | ast_sel<true, YAMLLineInner_t, Exp_t> content; | ||
609 | AST_MEMBER(YAMLLineContent, &content) | ||
610 | AST_END(YAMLLineContent) | ||
611 | |||
612 | AST_NODE(YAMLLine) | ||
613 | ast_ptr<true, YAMLIndent_t> indent; | ||
614 | ast_list<true, YAMLLineContent_t> segments; | ||
615 | AST_MEMBER(YAMLLine, &indent, &segments) | ||
616 | AST_END(YAMLLine) | ||
617 | |||
618 | AST_NODE(YAMLMultiline) | ||
619 | ast_ptr<true, Seperator_t> sep; | ||
620 | ast_list<true, YAMLLine_t> lines; | ||
621 | AST_MEMBER(YAMLMultiline, &sep, &lines) | ||
622 | AST_END(YAMLMultiline) | ||
623 | |||
590 | AST_NODE(String) | 624 | AST_NODE(String) |
591 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t> str; | 625 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t, YAMLMultiline_t> str; |
592 | AST_MEMBER(String, &str) | 626 | AST_MEMBER(String, &str) |
593 | AST_END(String) | 627 | AST_END(String) |
594 | 628 | ||
@@ -639,9 +673,14 @@ AST_END(TableAppendingOp) | |||
639 | AST_LEAF(PlainItem) | 673 | AST_LEAF(PlainItem) |
640 | AST_END(PlainItem) | 674 | AST_END(PlainItem) |
641 | 675 | ||
676 | AST_NODE(ReversedIndex) | ||
677 | ast_ptr<false, Exp_t> modifier; | ||
678 | AST_MEMBER(ReversedIndex, &modifier) | ||
679 | AST_END(ReversedIndex) | ||
680 | |||
642 | AST_NODE(ChainValue) | 681 | AST_NODE(ChainValue) |
643 | ast_ptr<true, Seperator_t> sep; | 682 | ast_ptr<true, Seperator_t> sep; |
644 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, | 683 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, ReversedIndex_t, |
645 | /*non-syntax-rule*/ PlainItem_t> items; | 684 | /*non-syntax-rule*/ PlainItem_t> items; |
646 | AST_MEMBER(ChainValue, &sep, &items) | 685 | AST_MEMBER(ChainValue, &sep, &items) |
647 | AST_END(ChainValue) | 686 | AST_END(ChainValue) |
@@ -725,8 +764,9 @@ AST_LEAF(GlobalOp) | |||
725 | AST_END(GlobalOp) | 764 | AST_END(GlobalOp) |
726 | 765 | ||
727 | AST_NODE(Global) | 766 | AST_NODE(Global) |
767 | ast_ptr<false, ConstAttrib_t> constAttrib; | ||
728 | ast_sel<true, ClassDecl_t, GlobalOp_t, GlobalValues_t> item; | 768 | ast_sel<true, ClassDecl_t, GlobalOp_t, GlobalValues_t> item; |
729 | AST_MEMBER(Global, &item) | 769 | AST_MEMBER(Global, &constAttrib, &item) |
730 | AST_END(Global) | 770 | AST_END(Global) |
731 | 771 | ||
732 | AST_LEAF(ExportDefault) | 772 | AST_LEAF(ExportDefault) |
@@ -742,15 +782,17 @@ AST_END(Export) | |||
742 | AST_NODE(FnArgDef) | 782 | AST_NODE(FnArgDef) |
743 | ast_sel<true, Variable_t, SelfItem_t> name; | 783 | ast_sel<true, Variable_t, SelfItem_t> name; |
744 | ast_ptr<false, ExistentialOp_t> op; | 784 | ast_ptr<false, ExistentialOp_t> op; |
785 | ast_ptr<false, Name_t> label; | ||
745 | ast_ptr<false, Exp_t> defaultValue; | 786 | ast_ptr<false, Exp_t> defaultValue; |
746 | AST_MEMBER(FnArgDef, &name, &op, &defaultValue) | 787 | AST_MEMBER(FnArgDef, &name, &op, &label, &defaultValue) |
747 | AST_END(FnArgDef) | 788 | AST_END(FnArgDef) |
748 | 789 | ||
749 | AST_NODE(FnArgDefList) | 790 | AST_NODE(FnArgDefList) |
750 | ast_ptr<true, Seperator_t> sep; | 791 | ast_ptr<true, Seperator_t> sep; |
751 | ast_list<false, FnArgDef_t> definitions; | 792 | ast_list<false, FnArgDef_t> definitions; |
752 | ast_ptr<false, VarArg_t> varArg; | 793 | ast_ptr<false, VarArg_t> varArg; |
753 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg) | 794 | ast_ptr<false, Name_t> label; |
795 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg, &label) | ||
754 | AST_END(FnArgDefList) | 796 | AST_END(FnArgDefList) |
755 | 797 | ||
756 | AST_NODE(OuterVarShadow) | 798 | AST_NODE(OuterVarShadow) |
@@ -838,9 +880,15 @@ AST_NODE(UnaryExp) | |||
838 | AST_MEMBER(UnaryExp, &ops, &expos, &inExp) | 880 | AST_MEMBER(UnaryExp, &ops, &expos, &inExp) |
839 | AST_END(UnaryExp) | 881 | AST_END(UnaryExp) |
840 | 882 | ||
883 | AST_NODE(SubBackcall) | ||
884 | ast_ptr<true, FnArrowBack_t> arrow; | ||
885 | ast_ptr<true, ChainValue_t> value; | ||
886 | AST_MEMBER(SubBackcall, &arrow, &value) | ||
887 | AST_END(SubBackcall) | ||
888 | |||
841 | AST_NODE(ExpListAssign) | 889 | AST_NODE(ExpListAssign) |
842 | ast_ptr<true, ExpList_t> expList; | 890 | ast_ptr<true, ExpList_t> expList; |
843 | ast_sel<false, Update_t, Assign_t> action; | 891 | ast_sel<false, Update_t, Assign_t, SubBackcall_t> action; |
844 | AST_MEMBER(ExpListAssign, &expList, &action) | 892 | AST_MEMBER(ExpListAssign, &expList, &action) |
845 | AST_END(ExpListAssign) | 893 | AST_END(ExpListAssign) |
846 | 894 | ||
@@ -856,7 +904,17 @@ AST_NODE(WhileLine) | |||
856 | AST_MEMBER(WhileLine, &type, &condition) | 904 | AST_MEMBER(WhileLine, &type, &condition) |
857 | AST_END(WhileLine) | 905 | AST_END(WhileLine) |
858 | 906 | ||
859 | AST_LEAF(BreakLoop) | 907 | AST_LEAF(Break) |
908 | AST_END(Break) | ||
909 | |||
910 | AST_LEAF(Continue) | ||
911 | AST_END(Continue) | ||
912 | |||
913 | AST_NODE(BreakLoop) | ||
914 | ast_sel<true, Break_t, Continue_t> type; | ||
915 | ast_ptr<false, Exp_t> value; | ||
916 | AST_MEMBER(BreakLoop, &type, &value) | ||
917 | std::string varBWV; | ||
860 | AST_END(BreakLoop) | 918 | AST_END(BreakLoop) |
861 | 919 | ||
862 | AST_NODE(PipeBody) | 920 | AST_NODE(PipeBody) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 68ce9b5..d676750 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -7,9 +7,12 @@ The above copyright notice and this permission notice shall be included in all c | |||
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ |
8 | 8 | ||
9 | #include <chrono> | 9 | #include <chrono> |
10 | #include <cmath> | ||
11 | #include <iomanip> | ||
10 | #include <memory> | 12 | #include <memory> |
11 | #include <optional> | 13 | #include <optional> |
12 | #include <set> | 14 | #include <set> |
15 | #include <sstream> | ||
13 | #include <stack> | 16 | #include <stack> |
14 | #include <string> | 17 | #include <string> |
15 | #include <unordered_map> | 18 | #include <unordered_map> |
@@ -75,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
75 | "close"s // Lua 5.4 | 78 | "close"s // Lua 5.4 |
76 | }; | 79 | }; |
77 | 80 | ||
78 | const std::string_view version = "0.27.4"sv; | 81 | const std::string_view version = "0.29.3"sv; |
79 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
80 | 83 | ||
81 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
@@ -162,12 +165,12 @@ public: | |||
162 | double compileTime = 0.0; | 165 | double compileTime = 0.0; |
163 | if (config.profiling) { | 166 | if (config.profiling) { |
164 | auto start = std::chrono::high_resolution_clock::now(); | 167 | auto start = std::chrono::high_resolution_clock::now(); |
165 | _info = _parser.parse<File_t>(codes); | 168 | _info = _parser.parse<File_t>(codes, config.lax); |
166 | auto stop = std::chrono::high_resolution_clock::now(); | 169 | auto stop = std::chrono::high_resolution_clock::now(); |
167 | std::chrono::duration<double> diff = stop - start; | 170 | std::chrono::duration<double> diff = stop - start; |
168 | parseTime = diff.count(); | 171 | parseTime = diff.count(); |
169 | } else { | 172 | } else { |
170 | _info = _parser.parse<File_t>(codes); | 173 | _info = _parser.parse<File_t>(codes, config.lax); |
171 | } | 174 | } |
172 | std::unique_ptr<GlobalVars> globals; | 175 | std::unique_ptr<GlobalVars> globals; |
173 | std::unique_ptr<Options> options; | 176 | std::unique_ptr<Options> options; |
@@ -426,8 +429,9 @@ private: | |||
426 | }; | 429 | }; |
427 | enum class VarType { | 430 | enum class VarType { |
428 | Local = 0, | 431 | Local = 0, |
429 | Const = 1, | 432 | LocalConst = 1, |
430 | Global = 2 | 433 | Global = 2, |
434 | GlobalConst = 3 | ||
431 | }; | 435 | }; |
432 | struct Scope { | 436 | struct Scope { |
433 | GlobalMode mode = GlobalMode::None; | 437 | GlobalMode mode = GlobalMode::None; |
@@ -555,7 +559,7 @@ private: | |||
555 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { | 559 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { |
556 | auto vars = it->vars.get(); | 560 | auto vars = it->vars.get(); |
557 | auto vit = vars->find(name); | 561 | auto vit = vars->find(name); |
558 | if (vit != vars->end() && vit->second != VarType::Global) { | 562 | if (vit != vars->end() && (vit->second == VarType::Local || vit->second == VarType::LocalConst)) { |
559 | local = true; | 563 | local = true; |
560 | break; | 564 | break; |
561 | } | 565 | } |
@@ -568,7 +572,7 @@ private: | |||
568 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { | 572 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { |
569 | auto vars = it->vars.get(); | 573 | auto vars = it->vars.get(); |
570 | auto vit = vars->find(name); | 574 | auto vit = vars->find(name); |
571 | if (vit != vars->end() && vit->second == VarType::Global) { | 575 | if (vit != vars->end() && (vit->second == VarType::Global || vit->second == VarType::GlobalConst)) { |
572 | global = true; | 576 | global = true; |
573 | break; | 577 | break; |
574 | } | 578 | } |
@@ -590,7 +594,7 @@ private: | |||
590 | auto vars = it->vars.get(); | 594 | auto vars = it->vars.get(); |
591 | auto vit = vars->find(name); | 595 | auto vit = vars->find(name); |
592 | if (vit != vars->end()) { | 596 | if (vit != vars->end()) { |
593 | isConst = (vit->second == VarType::Const); | 597 | isConst = (vit->second == VarType::LocalConst || vit->second == VarType::GlobalConst); |
594 | break; | 598 | break; |
595 | } | 599 | } |
596 | if (checkShadowScopeOnly && it->allows) break; | 600 | if (checkShadowScopeOnly && it->allows) break; |
@@ -871,9 +875,9 @@ private: | |||
871 | return false; | 875 | return false; |
872 | } | 876 | } |
873 | 877 | ||
874 | void markVarConst(const std::string& name) { | 878 | void markVarLocalConst(const std::string& name) { |
875 | auto& scope = _scopes.back(); | 879 | auto& scope = _scopes.back(); |
876 | scope.vars->insert_or_assign(name, VarType::Const); | 880 | scope.vars->insert_or_assign(name, VarType::LocalConst); |
877 | } | 881 | } |
878 | 882 | ||
879 | void markVarShadowed() { | 883 | void markVarShadowed() { |
@@ -892,6 +896,11 @@ private: | |||
892 | scope.vars->insert_or_assign(name, VarType::Global); | 896 | scope.vars->insert_or_assign(name, VarType::Global); |
893 | } | 897 | } |
894 | 898 | ||
899 | void markVarGlobalConst(const std::string& name) { | ||
900 | auto& scope = _scopes.back(); | ||
901 | scope.vars->insert_or_assign(name, VarType::GlobalConst); | ||
902 | } | ||
903 | |||
895 | void addToAllowList(const std::string& name) { | 904 | void addToAllowList(const std::string& name) { |
896 | auto& scope = _scopes.back(); | 905 | auto& scope = _scopes.back(); |
897 | scope.allows->insert(name); | 906 | scope.allows->insert(name); |
@@ -1249,7 +1258,7 @@ private: | |||
1249 | 1258 | ||
1250 | template <class T> | 1259 | template <class T> |
1251 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { | 1260 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { |
1252 | auto res = _parser.parse<T>(std::string(codes)); | 1261 | auto res = _parser.parse<T>(std::string(codes), false); |
1253 | if (res.error) { | 1262 | if (res.error) { |
1254 | throw CompileError(res.error.value().msg, parent); | 1263 | throw CompileError(res.error.value().msg, parent); |
1255 | } | 1264 | } |
@@ -1272,6 +1281,8 @@ private: | |||
1272 | Common, | 1281 | Common, |
1273 | EndWithColon, | 1282 | EndWithColon, |
1274 | EndWithEOP, | 1283 | EndWithEOP, |
1284 | EndWithSlice, | ||
1285 | HasRIndex, | ||
1275 | HasEOP, | 1286 | HasEOP, |
1276 | HasKeyword, | 1287 | HasKeyword, |
1277 | HasUnicode, | 1288 | HasUnicode, |
@@ -1290,6 +1301,9 @@ private: | |||
1290 | if (ast_is<ExistentialOp_t>(chainValue->items.back())) { | 1301 | if (ast_is<ExistentialOp_t>(chainValue->items.back())) { |
1291 | return ChainType::EndWithEOP; | 1302 | return ChainType::EndWithEOP; |
1292 | } | 1303 | } |
1304 | if (ast_is<Slice_t>(chainValue->items.back())) { | ||
1305 | return ChainType::EndWithSlice; | ||
1306 | } | ||
1293 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { | 1307 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { |
1294 | if (dot->name.is<Metatable_t>()) { | 1308 | if (dot->name.is<Metatable_t>()) { |
1295 | return ChainType::Metatable; | 1309 | return ChainType::Metatable; |
@@ -1315,6 +1329,8 @@ private: | |||
1315 | } | 1329 | } |
1316 | } else if (ast_is<ExistentialOp_t>(item)) { | 1330 | } else if (ast_is<ExistentialOp_t>(item)) { |
1317 | return ChainType::HasEOP; | 1331 | return ChainType::HasEOP; |
1332 | } else if (ast_is<ReversedIndex_t>(item)) { | ||
1333 | return ChainType::HasRIndex; | ||
1318 | } | 1334 | } |
1319 | } | 1335 | } |
1320 | return type; | 1336 | return type; |
@@ -1837,6 +1853,7 @@ private: | |||
1837 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(value), out); break; | 1853 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(value), out); break; |
1838 | case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; | 1854 | case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; |
1839 | case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; | 1855 | case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; |
1856 | case id<Repeat_t>(): transformRepeat(static_cast<Repeat_t*>(value), out); break; | ||
1840 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; | 1857 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; |
1841 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; | 1858 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; |
1842 | case id<Comprehension_t>(): { | 1859 | case id<Comprehension_t>(): { |
@@ -2048,13 +2065,16 @@ private: | |||
2048 | if (item.targetVar.empty()) { | 2065 | if (item.targetVar.empty()) { |
2049 | throw CompileError("can only declare variable as const"sv, item.target); | 2066 | throw CompileError("can only declare variable as const"sv, item.target); |
2050 | } | 2067 | } |
2051 | markVarConst(item.targetVar); | 2068 | markVarLocalConst(item.targetVar); |
2052 | } | 2069 | } |
2053 | } | 2070 | } |
2054 | } | 2071 | } |
2055 | } | 2072 | } |
2056 | 2073 | ||
2057 | bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | 2074 | bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { |
2075 | if (assignment->action.is<SubBackcall_t>()) { | ||
2076 | YUEE("AST node mismatch", assignment->action); | ||
2077 | } | ||
2058 | checkAssignable(assignment->expList); | 2078 | checkAssignable(assignment->expList); |
2059 | BLOCK_START | 2079 | BLOCK_START |
2060 | auto assign = ast_cast<Assign_t>(assignment->action); | 2080 | auto assign = ast_cast<Assign_t>(assignment->action); |
@@ -2317,6 +2337,17 @@ private: | |||
2317 | out.back().insert(0, preDefine); | 2337 | out.back().insert(0, preDefine); |
2318 | return false; | 2338 | return false; |
2319 | } | 2339 | } |
2340 | case id<Try_t>(): { | ||
2341 | auto tryNode = static_cast<Try_t*>(value); | ||
2342 | if (tryNode->eop) { | ||
2343 | auto assignList = assignment->expList.get(); | ||
2344 | std::string preDefine = getPreDefineLine(assignment); | ||
2345 | transformTry(tryNode, out, ExpUsage::Assignment, assignList); | ||
2346 | out.back().insert(0, preDefine); | ||
2347 | return false; | ||
2348 | } | ||
2349 | break; | ||
2350 | } | ||
2320 | case id<Switch_t>(): { | 2351 | case id<Switch_t>(): { |
2321 | auto switchNode = static_cast<Switch_t*>(value); | 2352 | auto switchNode = static_cast<Switch_t*>(value); |
2322 | auto assignList = assignment->expList.get(); | 2353 | auto assignList = assignment->expList.get(); |
@@ -2388,6 +2419,13 @@ private: | |||
2388 | out.back().insert(0, preDefine); | 2419 | out.back().insert(0, preDefine); |
2389 | return false; | 2420 | return false; |
2390 | } | 2421 | } |
2422 | case id<Repeat_t>(): { | ||
2423 | auto expList = assignment->expList.get(); | ||
2424 | std::string preDefine = getPreDefineLine(assignment); | ||
2425 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out, expList); | ||
2426 | out.back().insert(0, preDefine); | ||
2427 | return false; | ||
2428 | } | ||
2391 | case id<TableLit_t>(): { | 2429 | case id<TableLit_t>(): { |
2392 | auto tableLit = static_cast<TableLit_t*>(value); | 2430 | auto tableLit = static_cast<TableLit_t*>(value); |
2393 | if (hasSpreadExp(tableLit->values.objects())) { | 2431 | if (hasSpreadExp(tableLit->values.objects())) { |
@@ -2440,12 +2478,14 @@ private: | |||
2440 | switch (type) { | 2478 | switch (type) { |
2441 | case ChainType::HasEOP: | 2479 | case ChainType::HasEOP: |
2442 | case ChainType::EndWithColon: | 2480 | case ChainType::EndWithColon: |
2481 | case ChainType::EndWithSlice: | ||
2443 | case ChainType::MetaFieldInvocation: { | 2482 | case ChainType::MetaFieldInvocation: { |
2444 | std::string preDefine = getPreDefineLine(assignment); | 2483 | std::string preDefine = getPreDefineLine(assignment); |
2445 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); | 2484 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); |
2446 | out.back().insert(0, preDefine); | 2485 | out.back().insert(0, preDefine); |
2447 | return false; | 2486 | return false; |
2448 | } | 2487 | } |
2488 | case ChainType::HasRIndex: | ||
2449 | case ChainType::HasKeyword: | 2489 | case ChainType::HasKeyword: |
2450 | case ChainType::HasUnicode: | 2490 | case ChainType::HasUnicode: |
2451 | case ChainType::Macro: | 2491 | case ChainType::Macro: |
@@ -2461,6 +2501,10 @@ private: | |||
2461 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); | 2501 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); |
2462 | if (info.destructures.empty()) { | 2502 | if (info.destructures.empty()) { |
2463 | transformAssignmentCommon(assignment, out); | 2503 | transformAssignmentCommon(assignment, out); |
2504 | if (assignment->expList->followStmt) { | ||
2505 | transformStatement(assignment->expList->followStmt, out); | ||
2506 | assignment->expList->followStmtProcessed = true; | ||
2507 | } | ||
2464 | return true; | 2508 | return true; |
2465 | } else { | 2509 | } else { |
2466 | auto x = assignment; | 2510 | auto x = assignment; |
@@ -2726,8 +2770,12 @@ private: | |||
2726 | temp.push_back(indent() + "end"s + nlr(x)); | 2770 | temp.push_back(indent() + "end"s + nlr(x)); |
2727 | } | 2771 | } |
2728 | out.push_back(join(temp)); | 2772 | out.push_back(join(temp)); |
2773 | if (assignment->expList->followStmt) { | ||
2774 | transformStatement(assignment->expList->followStmt, out); | ||
2775 | assignment->expList->followStmtProcessed = true; | ||
2776 | } | ||
2777 | return false; | ||
2729 | } | 2778 | } |
2730 | return false; | ||
2731 | } | 2779 | } |
2732 | 2780 | ||
2733 | void transformAssignItem(ast_node* value, str_list& out) { | 2781 | void transformAssignItem(ast_node* value, str_list& out) { |
@@ -2793,20 +2841,46 @@ private: | |||
2793 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); | 2841 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); |
2794 | std::list<DestructItem> pairs; | 2842 | std::list<DestructItem> pairs; |
2795 | int index = 0; | 2843 | int index = 0; |
2844 | int count = 0; | ||
2845 | bool hasSpread = false; | ||
2796 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); | 2846 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); |
2797 | for (auto pair : *tableItems) { | 2847 | for (auto pair : *tableItems) { |
2798 | switch (pair->get_id()) { | 2848 | switch (pair->get_id()) { |
2799 | case id<Exp_t>(): | 2849 | case id<Exp_t>(): |
2800 | case id<NormalDef_t>(): { | 2850 | case id<NormalDef_t>(): { |
2851 | ++index; | ||
2801 | Exp_t* defVal = nullptr; | 2852 | Exp_t* defVal = nullptr; |
2802 | if (auto nd = ast_cast<NormalDef_t>(pair)) { | 2853 | if (auto nd = ast_cast<NormalDef_t>(pair)) { |
2803 | pair = nd->item.get(); | 2854 | pair = nd->item.get(); |
2804 | defVal = nd->defVal.get(); | 2855 | defVal = nd->defVal.get(); |
2805 | } | 2856 | } |
2806 | ++index; | 2857 | bool assignable = false; |
2807 | if (!varDefOnly && !isAssignable(static_cast<Exp_t*>(pair))) { | 2858 | try { |
2859 | assignable = isAssignable(static_cast<Exp_t*>(pair)); | ||
2860 | } catch (const CompileError& e) { | ||
2861 | if (!varDefOnly) throw e; | ||
2862 | } | ||
2863 | if (!assignable && !varDefOnly) { | ||
2864 | if (optional) break; | ||
2808 | throw CompileError("can't destructure value"sv, pair); | 2865 | throw CompileError("can't destructure value"sv, pair); |
2809 | } | 2866 | } |
2867 | ast_ptr<true, ast_node> indexItem; | ||
2868 | if (hasSpread) { | ||
2869 | int rIndex = count - index; | ||
2870 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), pair)); | ||
2871 | } else { | ||
2872 | indexItem.set(toAst<Exp_t>(std::to_string(index), pair)); | ||
2873 | } | ||
2874 | if (optional && varDefOnly && !assignable) { | ||
2875 | if (defVal) { | ||
2876 | throw CompileError("default value is not supported here"sv, defVal); | ||
2877 | } | ||
2878 | auto exp = static_cast<Exp_t*>(pair); | ||
2879 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
2880 | chain->items.push_back(indexItem); | ||
2881 | pairs.push_back({exp, Empty, chain, nullptr}); | ||
2882 | break; | ||
2883 | } | ||
2810 | auto value = singleValueFrom(pair); | 2884 | auto value = singleValueFrom(pair); |
2811 | auto item = value->item.get(); | 2885 | auto item = value->item.get(); |
2812 | ast_node* subExp = ast_cast<SimpleTable_t>(item); | 2886 | ast_node* subExp = ast_cast<SimpleTable_t>(item); |
@@ -2817,7 +2891,6 @@ private: | |||
2817 | throw CompileError("default value is not supported here"sv, defVal); | 2891 | throw CompileError("default value is not supported here"sv, defVal); |
2818 | } | 2892 | } |
2819 | } | 2893 | } |
2820 | auto indexItem = toAst<Exp_t>(std::to_string(index), value); | ||
2821 | for (auto& p : subPairs) { | 2894 | for (auto& p : subPairs) { |
2822 | if (sep) p.structure->items.push_front(sep); | 2895 | if (sep) p.structure->items.push_front(sep); |
2823 | p.structure->items.push_front(indexItem); | 2896 | p.structure->items.push_front(indexItem); |
@@ -2828,7 +2901,6 @@ private: | |||
2828 | auto varName = singleVariableFrom(exp, AccessType::None); | 2901 | auto varName = singleVariableFrom(exp, AccessType::None); |
2829 | if (varName == "_"sv) break; | 2902 | if (varName == "_"sv) break; |
2830 | auto chain = exp->new_ptr<ChainValue_t>(); | 2903 | auto chain = exp->new_ptr<ChainValue_t>(); |
2831 | auto indexItem = toAst<Exp_t>(std::to_string(index), exp); | ||
2832 | chain->items.push_back(indexItem); | 2904 | chain->items.push_back(indexItem); |
2833 | pairs.push_back({exp, | 2905 | pairs.push_back({exp, |
2834 | varName, | 2906 | varName, |
@@ -2886,7 +2958,25 @@ private: | |||
2886 | } | 2958 | } |
2887 | } | 2959 | } |
2888 | if (auto exp = np->value.as<Exp_t>()) { | 2960 | if (auto exp = np->value.as<Exp_t>()) { |
2889 | if (!varDefOnly && !isAssignable(exp)) throw CompileError("can't do destructure value"sv, exp); | 2961 | bool assignable = false; |
2962 | try { | ||
2963 | assignable = isAssignable(exp); | ||
2964 | } catch (const CompileError& e) { | ||
2965 | if (!varDefOnly) throw e; | ||
2966 | } | ||
2967 | if (!assignable && !varDefOnly) { | ||
2968 | if (optional) break; | ||
2969 | throw CompileError("can't destructure value"sv, pair); | ||
2970 | } | ||
2971 | if (optional && varDefOnly && !assignable) { | ||
2972 | if (defVal) { | ||
2973 | throw CompileError("default value is not supported here"sv, defVal); | ||
2974 | } | ||
2975 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
2976 | if (keyIndex) chain->items.push_back(keyIndex); | ||
2977 | pairs.push_back({exp, Empty, chain, nullptr}); | ||
2978 | break; | ||
2979 | } | ||
2890 | auto item = singleValueFrom(exp)->item.get(); | 2980 | auto item = singleValueFrom(exp)->item.get(); |
2891 | ast_node* subExp = ast_cast<SimpleTable_t>(item); | 2981 | ast_node* subExp = ast_cast<SimpleTable_t>(item); |
2892 | if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) { | 2982 | if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) { |
@@ -2935,7 +3025,13 @@ private: | |||
2935 | auto tb = static_cast<TableBlockIndent_t*>(pair); | 3025 | auto tb = static_cast<TableBlockIndent_t*>(pair); |
2936 | ++index; | 3026 | ++index; |
2937 | auto subPairs = destructFromExp(tb, varDefOnly, optional); | 3027 | auto subPairs = destructFromExp(tb, varDefOnly, optional); |
2938 | auto indexItem = toAst<Exp_t>(std::to_string(index), tb); | 3028 | ast_ptr<true, ast_node> indexItem; |
3029 | if (hasSpread) { | ||
3030 | int rIndex = count - index; | ||
3031 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), tb)); | ||
3032 | } else { | ||
3033 | indexItem.set(toAst<Exp_t>(std::to_string(index), tb)); | ||
3034 | } | ||
2939 | for (auto& p : subPairs) { | 3035 | for (auto& p : subPairs) { |
2940 | if (sep) p.structure->items.push_front(sep); | 3036 | if (sep) p.structure->items.push_front(sep); |
2941 | p.structure->items.push_front(indexItem); | 3037 | p.structure->items.push_front(indexItem); |
@@ -2992,6 +3088,42 @@ private: | |||
2992 | subMetaDestruct->values.push_back(newPairDef); | 3088 | subMetaDestruct->values.push_back(newPairDef); |
2993 | break; | 3089 | break; |
2994 | } | 3090 | } |
3091 | case id<SpreadListExp_t>(): | ||
3092 | case id<SpreadExp_t>(): { | ||
3093 | ++index; | ||
3094 | if (hasSpread) { | ||
3095 | throw CompileError("duplicated spread expression"sv, pair); | ||
3096 | } | ||
3097 | hasSpread = true; | ||
3098 | for (auto item : *tableItems) { | ||
3099 | if (ast_is< | ||
3100 | SpreadListExp_t, SpreadExp_t, | ||
3101 | TableBlockIndent_t, | ||
3102 | Exp_t, NormalDef_t>(item)) { | ||
3103 | count++; | ||
3104 | } | ||
3105 | } | ||
3106 | Exp_t* exp = nullptr; | ||
3107 | if (auto se = ast_cast<SpreadExp_t>(pair)) { | ||
3108 | exp = se->exp.get(); | ||
3109 | } else { | ||
3110 | exp = ast_to<SpreadListExp_t>(pair)->exp.get(); | ||
3111 | } | ||
3112 | auto varName = singleVariableFrom(exp, AccessType::None); | ||
3113 | if (varName == "_"sv) break; | ||
3114 | int start = index; | ||
3115 | int stop = index - count - 1; | ||
3116 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
3117 | auto slice = toAst<Slice_t>( | ||
3118 | '[' + (start == 1 ? Empty : std::to_string(start)) + ',' + (stop == -1 ? Empty : std::to_string(stop)) + ']', exp); | ||
3119 | chain->items.push_back(slice); | ||
3120 | auto nil = toAst<Exp_t>("nil"sv, slice); | ||
3121 | pairs.push_back({exp, | ||
3122 | varName, | ||
3123 | chain, | ||
3124 | nil.get()}); | ||
3125 | break; | ||
3126 | } | ||
2995 | default: YUEE("AST node mismatch", pair); break; | 3127 | default: YUEE("AST node mismatch", pair); break; |
2996 | } | 3128 | } |
2997 | } | 3129 | } |
@@ -3108,7 +3240,11 @@ private: | |||
3108 | break; | 3240 | break; |
3109 | default: YUEE("AST node mismatch", destructNode); break; | 3241 | default: YUEE("AST node mismatch", destructNode); break; |
3110 | } | 3242 | } |
3111 | if (dlist->empty()) throw CompileError("expect items to be destructured"sv, destructNode); | 3243 | if (dlist->empty()) { |
3244 | if (!optional) { | ||
3245 | throw CompileError("expect items to be destructured"sv, destructNode); | ||
3246 | } | ||
3247 | } | ||
3112 | for (auto item : *dlist) { | 3248 | for (auto item : *dlist) { |
3113 | switch (item->get_id()) { | 3249 | switch (item->get_id()) { |
3114 | case id<MetaVariablePairDef_t>(): { | 3250 | case id<MetaVariablePairDef_t>(): { |
@@ -3244,7 +3380,9 @@ private: | |||
3244 | simpleValue->value.set(tab); | 3380 | simpleValue->value.set(tab); |
3245 | auto pairs = destructFromExp(newExp(simpleValue, expr), varDefOnly, optional); | 3381 | auto pairs = destructFromExp(newExp(simpleValue, expr), varDefOnly, optional); |
3246 | if (pairs.empty()) { | 3382 | if (pairs.empty()) { |
3247 | throw CompileError("expect items to be destructured"sv, tab); | 3383 | if (!optional) { |
3384 | throw CompileError("expect items to be destructured"sv, tab); | ||
3385 | } | ||
3248 | } | 3386 | } |
3249 | destruct.items = std::move(pairs); | 3387 | destruct.items = std::move(pairs); |
3250 | if (!varDefOnly) { | 3388 | if (!varDefOnly) { |
@@ -3283,7 +3421,7 @@ private: | |||
3283 | destruct.valueVar.clear(); | 3421 | destruct.valueVar.clear(); |
3284 | } | 3422 | } |
3285 | } | 3423 | } |
3286 | destructs.push_back(destruct); | 3424 | destructs.push_back(std::move(destruct)); |
3287 | } | 3425 | } |
3288 | } | 3426 | } |
3289 | } else { | 3427 | } else { |
@@ -4202,12 +4340,22 @@ private: | |||
4202 | 4340 | ||
4203 | std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { | 4341 | std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { |
4204 | if (checkUpValueFuncAvailable(exp)) { | 4342 | if (checkUpValueFuncAvailable(exp)) { |
4343 | auto block = exp->new_ptr<Block_t>(); | ||
4344 | if (auto sVal = simpleSingleValueFrom(exp)) { | ||
4345 | if (auto doNode = sVal->value.as<Do_t>()) { | ||
4346 | if (auto blk = doNode->body->content.as<Block_t>()) { | ||
4347 | block->statements.dup(blk->statements); | ||
4348 | } else { | ||
4349 | block->statements.push_back(doNode->body->content.to<Statement_t>()); | ||
4350 | } | ||
4351 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); | ||
4352 | } | ||
4353 | } | ||
4205 | auto returnNode = exp->new_ptr<Return_t>(); | 4354 | auto returnNode = exp->new_ptr<Return_t>(); |
4206 | returnNode->explicitReturn = false; | 4355 | returnNode->explicitReturn = false; |
4207 | auto returnList = exp->new_ptr<ExpListLow_t>(); | 4356 | auto returnList = exp->new_ptr<ExpListLow_t>(); |
4208 | returnList->exprs.push_back(exp); | 4357 | returnList->exprs.push_back(exp); |
4209 | returnNode->valueList.set(returnList); | 4358 | returnNode->valueList.set(returnList); |
4210 | auto block = exp->new_ptr<Block_t>(); | ||
4211 | auto stmt = exp->new_ptr<Statement_t>(); | 4359 | auto stmt = exp->new_ptr<Statement_t>(); |
4212 | stmt->content.set(returnNode); | 4360 | stmt->content.set(returnNode); |
4213 | block->statements.push_back(stmt); | 4361 | block->statements.push_back(stmt); |
@@ -4284,7 +4432,9 @@ private: | |||
4284 | return false; | 4432 | return false; |
4285 | }; | 4433 | }; |
4286 | switch (usage) { | 4434 | switch (usage) { |
4287 | case ExpUsage::Common: YUEE("AST node mismatch", x); return; | 4435 | case ExpUsage::Common: |
4436 | YUEE("AST node mismatch", x); | ||
4437 | return; | ||
4288 | case ExpUsage::Return: | 4438 | case ExpUsage::Return: |
4289 | case ExpUsage::Closure: { | 4439 | case ExpUsage::Closure: { |
4290 | prepareValue(); | 4440 | prepareValue(); |
@@ -4407,6 +4557,7 @@ private: | |||
4407 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; | 4557 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; |
4408 | case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; | 4558 | case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; |
4409 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; | 4559 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; |
4560 | case id<Repeat_t>(): transformRepeatClosure(static_cast<Repeat_t*>(value), out); break; | ||
4410 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; | 4561 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; |
4411 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; | 4562 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; |
4412 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; | 4563 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; |
@@ -4726,11 +4877,7 @@ private: | |||
4726 | auto newBody = x->new_ptr<Body_t>(); | 4877 | auto newBody = x->new_ptr<Body_t>(); |
4727 | newBody->content.set(followingBlock); | 4878 | newBody->content.set(followingBlock); |
4728 | { | 4879 | { |
4729 | auto doNode = x->new_ptr<Do_t>(); | 4880 | if (auto result = upValueFuncFromBlock(followingBlock.get(), &argNames, false, true)) { |
4730 | doNode->body.set(newBody); | ||
4731 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
4732 | simpleValue->value.set(doNode); | ||
4733 | if (auto result = upValueFuncFromExp(newExp(simpleValue, x), &argNames, true)) { | ||
4734 | auto [funcName, args] = std::move(*result); | 4881 | auto [funcName, args] = std::move(*result); |
4735 | str_list finalArgs; | 4882 | str_list finalArgs; |
4736 | for (const auto& arg : args) { | 4883 | for (const auto& arg : args) { |
@@ -4738,9 +4885,13 @@ private: | |||
4738 | finalArgs.push_back(arg); | 4885 | finalArgs.push_back(arg); |
4739 | } | 4886 | } |
4740 | } | 4887 | } |
4741 | newBlock->statements.push_back(toAst<Statement_t>(funcName + ' ' + join(finalArgs, ","sv), x)); | 4888 | newBlock->statements.push_back(toAst<Statement_t>(funcName + ' ' + (finalArgs.empty() ? "nil"s : join(finalArgs, ","sv)), x)); |
4742 | auto sVal = singleValueFrom(static_cast<Statement_t*>(newBlock->statements.back())->content.to<ExpListAssign_t>()->expList); | 4889 | auto sVal = singleValueFrom(static_cast<Statement_t*>(newBlock->statements.back())->content.to<ExpListAssign_t>()->expList); |
4743 | ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back())->args.dup(newInvoke->args); | 4890 | auto invokArgs = ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back()); |
4891 | if (finalArgs.empty()) { | ||
4892 | invokArgs->args.clear(); | ||
4893 | } | ||
4894 | invokArgs->args.dup(newInvoke->args); | ||
4744 | transformBlock(newBlock, out, usage, assignList, isRoot); | 4895 | transformBlock(newBlock, out, usage, assignList, isRoot); |
4745 | return; | 4896 | return; |
4746 | } | 4897 | } |
@@ -4797,7 +4948,7 @@ private: | |||
4797 | auto varName = variableToString(ast_to<Variable_t>(var)); | 4948 | auto varName = variableToString(ast_to<Variable_t>(var)); |
4798 | auto closeVar = getUnusedName("_close_"sv); | 4949 | auto closeVar = getUnusedName("_close_"sv); |
4799 | addToScope(closeVar); | 4950 | addToScope(closeVar); |
4800 | getCloses.push_back(closeVar + "=if type("s + varName + ") in ['table', 'userdata'] then assert "s + varName + ".<> and "s + varName +".<close>, \""s + "variable '"s + varName + "' got a non-closable value\" elseif "s + varName + " == nil then nil else error \""s + "variable '"s + varName + "' got a non-closable value\""); | 4951 | getCloses.push_back(closeVar + "=if type("s + varName + ") in ['table', 'userdata'] then assert "s + varName + ".<> and "s + varName + ".<close>, \""s + "variable '"s + varName + "' got a non-closable value\" elseif "s + varName + " == nil then nil else error \""s + "variable '"s + varName + "' got a non-closable value\""); |
4801 | doCloses.push_front(closeVar + "? "s + varName); | 4952 | doCloses.push_front(closeVar + "? "s + varName); |
4802 | } | 4953 | } |
4803 | popScope(); | 4954 | popScope(); |
@@ -4817,6 +4968,38 @@ private: | |||
4817 | newBlock->statements.push_back(toAst<Statement_t>("if "s + okVar + " then return ... else error ..."s, x)); | 4968 | newBlock->statements.push_back(toAst<Statement_t>("if "s + okVar + " then return ... else error ..."s, x)); |
4818 | transformBlock(newBlock, out, usage, assignList, isRoot); | 4969 | transformBlock(newBlock, out, usage, assignList, isRoot); |
4819 | return; | 4970 | return; |
4971 | } else if (auto expListAssign = stmt->content.as<ExpListAssign_t>(); | ||
4972 | expListAssign && expListAssign->action && expListAssign->action.is<SubBackcall_t>()) { | ||
4973 | auto x = *nodes.begin(); | ||
4974 | auto newBlock = x->new_ptr<Block_t>(); | ||
4975 | if (it != nodes.begin()) { | ||
4976 | for (auto i = nodes.begin(); i != it; ++i) { | ||
4977 | newBlock->statements.push_back(*i); | ||
4978 | } | ||
4979 | } | ||
4980 | auto doBackcall = static_cast<SubBackcall_t*>(expListAssign->action.get()); | ||
4981 | auto backcall = expListAssign->new_ptr<Backcall_t>(); | ||
4982 | auto argsDef = backcall->new_ptr<FnArgsDef_t>(); | ||
4983 | try { | ||
4984 | auto defList = toAst<FnArgDefList_t>(YueFormat{}.toString(expListAssign->expList), expListAssign->expList); | ||
4985 | argsDef->defList.set(defList); | ||
4986 | } catch (const std::exception&) { | ||
4987 | throw CompileError("backcall syntax error", backcall); | ||
4988 | } | ||
4989 | backcall->argsDef.set(argsDef); | ||
4990 | backcall->arrow.set(doBackcall->arrow); | ||
4991 | backcall->value.set(doBackcall->value); | ||
4992 | auto newStmt = backcall->new_ptr<Statement_t>(); | ||
4993 | newStmt->content.set(backcall); | ||
4994 | newStmt->comments.dup(stmt->comments); | ||
4995 | newStmt->appendix.set(stmt->appendix); | ||
4996 | newBlock->statements.push_back(newStmt); | ||
4997 | auto ait = it; | ||
4998 | for (auto i = ++ait; i != nodes.end(); ++i) { | ||
4999 | newBlock->statements.push_back(*i); | ||
5000 | } | ||
5001 | transformBlock(newBlock, out, usage, assignList, isRoot); | ||
5002 | return; | ||
4820 | } | 5003 | } |
4821 | if (auto local = stmt->content.as<Local_t>()) { | 5004 | if (auto local = stmt->content.as<Local_t>()) { |
4822 | if (!local->collected) { | 5005 | if (!local->collected) { |
@@ -4988,36 +5171,45 @@ private: | |||
4988 | if (!nodes.empty()) { | 5171 | if (!nodes.empty()) { |
4989 | str_list temp; | 5172 | str_list temp; |
4990 | for (auto node : nodes) { | 5173 | for (auto node : nodes) { |
4991 | currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None; | 5174 | auto transformNode = [&]() { |
4992 | transformStatement(static_cast<Statement_t*>(node), temp); | 5175 | currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None; |
4993 | if (isRoot && !_rootDefs.empty()) { | 5176 | transformStatement(static_cast<Statement_t*>(node), temp); |
4994 | auto last = std::move(temp.back()); | 5177 | if (isRoot && !_rootDefs.empty()) { |
4995 | temp.pop_back(); | 5178 | auto last = std::move(temp.back()); |
4996 | temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); | 5179 | temp.pop_back(); |
4997 | _rootDefs.clear(); | 5180 | temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); |
4998 | temp.push_back(std::move(last)); | 5181 | _rootDefs.clear(); |
4999 | } | 5182 | temp.push_back(std::move(last)); |
5000 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { | 5183 | } |
5001 | auto rit = ++temp.rbegin(); | 5184 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { |
5002 | if (rit != temp.rend() && !rit->empty()) { | 5185 | auto rit = ++temp.rbegin(); |
5003 | auto index = std::string::npos; | 5186 | if (rit != temp.rend() && !rit->empty()) { |
5004 | if (_config.reserveLineNumber) { | 5187 | auto index = std::string::npos; |
5005 | index = rit->rfind(" -- "sv); | 5188 | if (_config.reserveLineNumber) { |
5006 | } else { | 5189 | index = rit->rfind(" -- "sv); |
5007 | index = rit->find_last_not_of('\n'); | 5190 | } else { |
5008 | if (index != std::string::npos) index++; | 5191 | index = rit->find_last_not_of('\n'); |
5009 | } | 5192 | if (index != std::string::npos) index++; |
5010 | if (index != std::string::npos) { | ||
5011 | auto ending = rit->substr(0, index); | ||
5012 | auto ind = ending.find_last_of(" \t\n"sv); | ||
5013 | if (ind != std::string::npos) { | ||
5014 | ending = ending.substr(ind + 1); | ||
5015 | } | 5193 | } |
5016 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | 5194 | if (index != std::string::npos) { |
5017 | rit->insert(index, ";"sv); | 5195 | auto ending = rit->substr(0, index); |
5196 | auto ind = ending.find_last_of(" \t\n"sv); | ||
5197 | if (ind != std::string::npos) { | ||
5198 | ending = ending.substr(ind + 1); | ||
5199 | } | ||
5200 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | ||
5201 | rit->insert(index, ";"sv); | ||
5202 | } | ||
5018 | } | 5203 | } |
5019 | } | 5204 | } |
5020 | } | 5205 | } |
5206 | }; | ||
5207 | if (_config.lax) { | ||
5208 | try { | ||
5209 | transformNode(); | ||
5210 | } catch (const CompileError&) { } | ||
5211 | } else { | ||
5212 | transformNode(); | ||
5021 | } | 5213 | } |
5022 | } | 5214 | } |
5023 | out.push_back(join(temp)); | 5215 | out.push_back(join(temp)); |
@@ -5226,18 +5418,29 @@ private: | |||
5226 | auto macroLit = macro->decl.to<MacroLit_t>(); | 5418 | auto macroLit = macro->decl.to<MacroLit_t>(); |
5227 | auto argsDef = macroLit->argsDef.get(); | 5419 | auto argsDef = macroLit->argsDef.get(); |
5228 | str_list newArgs; | 5420 | str_list newArgs; |
5421 | str_list argChecks; | ||
5422 | bool hasCheck = false; | ||
5229 | if (argsDef) { | 5423 | if (argsDef) { |
5230 | for (auto def_ : argsDef->definitions.objects()) { | 5424 | for (auto def_ : argsDef->definitions.objects()) { |
5231 | auto def = static_cast<FnArgDef_t*>(def_); | 5425 | auto def = static_cast<FnArgDef_t*>(def_); |
5232 | if (def->name.is<SelfItem_t>()) { | 5426 | if (def->name.is<SelfItem_t>()) { |
5233 | throw CompileError("self name is not supported for macro function argument"sv, def->name); | 5427 | throw CompileError("self name is not supported for macro function argument"sv, def->name); |
5234 | } else { | 5428 | } else { |
5429 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
5430 | if (def->label) { | ||
5431 | hasCheck = true; | ||
5432 | const auto& astName = argChecks.emplace_back(_parser.toString(def->label)); | ||
5433 | if (!_parser.hasAST(astName)) { | ||
5434 | throw CompileError("invalid AST name"sv, def->label); | ||
5435 | } | ||
5436 | } else { | ||
5437 | argChecks.emplace_back(); | ||
5438 | } | ||
5235 | std::string defVal; | 5439 | std::string defVal; |
5236 | if (def->defaultValue) { | 5440 | if (def->defaultValue) { |
5237 | defVal = _parser.toString(def->defaultValue); | 5441 | defVal = _parser.toString(def->defaultValue); |
5238 | Utils::trim(defVal); | 5442 | Utils::trim(defVal); |
5239 | defVal.insert(0, "=[==========["sv); | 5443 | defVal = '=' + Utils::toLuaDoubleString(defVal); |
5240 | defVal.append("]==========]"sv); | ||
5241 | } | 5444 | } |
5242 | newArgs.emplace_back(_parser.toString(def->name) + defVal); | 5445 | newArgs.emplace_back(_parser.toString(def->name) + defVal); |
5243 | } | 5446 | } |
@@ -5245,6 +5448,14 @@ private: | |||
5245 | if (argsDef->varArg) { | 5448 | if (argsDef->varArg) { |
5246 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); | 5449 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); |
5247 | } | 5450 | } |
5451 | if (argsDef->label) { | ||
5452 | hasCheck = true; | ||
5453 | const auto& astName = _parser.toString(argsDef->label); | ||
5454 | if (!_parser.hasAST(astName)) { | ||
5455 | throw CompileError("invalid AST name"sv, argsDef->label); | ||
5456 | } | ||
5457 | argChecks.emplace_back("..."s + astName); | ||
5458 | } | ||
5248 | } | 5459 | } |
5249 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); | 5460 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); |
5250 | auto chunkName = "=(macro "s + macroName + ')'; | 5461 | auto chunkName = "=(macro "s + macroName + ')'; |
@@ -5275,6 +5486,24 @@ private: | |||
5275 | throw CompileError("failed to generate macro function\n"s + err, macroLit); | 5486 | throw CompileError("failed to generate macro function\n"s + err, macroLit); |
5276 | } // cur true macro | 5487 | } // cur true macro |
5277 | lua_remove(L, -2); // cur macro | 5488 | lua_remove(L, -2); // cur macro |
5489 | if (hasCheck) { | ||
5490 | lua_createtable(L, 0, 0); // cur macro checks | ||
5491 | int i = 1; | ||
5492 | for (const auto& check : argChecks) { | ||
5493 | if (check.empty()) { | ||
5494 | lua_pushboolean(L, 0); | ||
5495 | lua_rawseti(L, -2, i); | ||
5496 | } else { | ||
5497 | lua_pushlstring(L, check.c_str(), check.size()); | ||
5498 | lua_rawseti(L, -2, i); | ||
5499 | } | ||
5500 | i++; | ||
5501 | } | ||
5502 | lua_createtable(L, 2, 0); // cur macro checks macrotab | ||
5503 | lua_insert(L, -3); // cur macrotab macro checks | ||
5504 | lua_rawseti(L, -3, 1); // macrotab[1] = checks, cur macrotab macro | ||
5505 | lua_rawseti(L, -2, 2); // macrotab[2] = macro, cur macrotab | ||
5506 | } // cur macro | ||
5278 | if (exporting && _config.exporting && !_config.module.empty()) { | 5507 | if (exporting && _config.exporting && !_config.module.empty()) { |
5279 | pushModuleTable(_config.module); // cur macro module | 5508 | pushModuleTable(_config.module); // cur macro module |
5280 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name | 5509 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name |
@@ -5349,6 +5578,9 @@ private: | |||
5349 | case id<While_t>(): | 5578 | case id<While_t>(): |
5350 | transformWhileInPlace(static_cast<While_t*>(value), out); | 5579 | transformWhileInPlace(static_cast<While_t*>(value), out); |
5351 | return; | 5580 | return; |
5581 | case id<Repeat_t>(): | ||
5582 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out); | ||
5583 | return; | ||
5352 | case id<For_t>(): | 5584 | case id<For_t>(): |
5353 | transformForInPlace(static_cast<For_t*>(value), out); | 5585 | transformForInPlace(static_cast<For_t*>(value), out); |
5354 | return; | 5586 | return; |
@@ -5429,7 +5661,11 @@ private: | |||
5429 | auto def = static_cast<FnArgDef_t*>(_def); | 5661 | auto def = static_cast<FnArgDef_t*>(_def); |
5430 | auto& arg = argItems.emplace_back(); | 5662 | auto& arg = argItems.emplace_back(); |
5431 | switch (def->name->get_id()) { | 5663 | switch (def->name->get_id()) { |
5432 | case id<Variable_t>(): arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); break; | 5664 | case id<Variable_t>(): { |
5665 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
5666 | arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); | ||
5667 | break; | ||
5668 | } | ||
5433 | case id<SelfItem_t>(): { | 5669 | case id<SelfItem_t>(): { |
5434 | assignSelf = true; | 5670 | assignSelf = true; |
5435 | if (def->op) { | 5671 | if (def->op) { |
@@ -5568,6 +5804,45 @@ private: | |||
5568 | } | 5804 | } |
5569 | } | 5805 | } |
5570 | 5806 | ||
5807 | bool transformChainEndWithSlice(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | ||
5808 | auto x = chainList.front(); | ||
5809 | if (ast_is<Slice_t>(chainList.back())) { | ||
5810 | auto comp = x->new_ptr<Comprehension_t>(); | ||
5811 | { | ||
5812 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
5813 | for (auto item : chainList) { | ||
5814 | chainValue->items.push_back(item); | ||
5815 | } | ||
5816 | auto itemVar = getUnusedName("_item_"sv); | ||
5817 | auto expCode = YueFormat{}.toString(chainValue); | ||
5818 | auto compCode = '[' + itemVar + " for "s + itemVar + " in *"s + expCode + ']'; | ||
5819 | comp.set(toAst<Comprehension_t>(compCode, x)); | ||
5820 | } | ||
5821 | switch (usage) { | ||
5822 | case ExpUsage::Assignment: { | ||
5823 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
5824 | simpleValue->value.set(comp); | ||
5825 | auto exp = newExp(simpleValue, x); | ||
5826 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
5827 | assignment->expList.set(assignList); | ||
5828 | auto assign = x->new_ptr<Assign_t>(); | ||
5829 | assign->values.push_back(exp); | ||
5830 | assignment->action.set(assign); | ||
5831 | transformAssignment(assignment, out); | ||
5832 | break; | ||
5833 | } | ||
5834 | case ExpUsage::Return: | ||
5835 | transformComprehension(comp, out, ExpUsage::Return); | ||
5836 | break; | ||
5837 | default: | ||
5838 | transformComprehension(comp, out, ExpUsage::Closure); | ||
5839 | break; | ||
5840 | } | ||
5841 | return true; | ||
5842 | } | ||
5843 | return false; | ||
5844 | } | ||
5845 | |||
5571 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | 5846 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { |
5572 | auto x = chainList.front(); | 5847 | auto x = chainList.front(); |
5573 | if (ast_is<ExistentialOp_t>(chainList.back())) { | 5848 | if (ast_is<ExistentialOp_t>(chainList.back())) { |
@@ -6085,7 +6360,7 @@ private: | |||
6085 | case id<ColonChainItem_t>(): | 6360 | case id<ColonChainItem_t>(): |
6086 | case id<Exp_t>(): | 6361 | case id<Exp_t>(): |
6087 | if (_withVars.empty()) { | 6362 | if (_withVars.empty()) { |
6088 | throw CompileError("short dot/colon and indexing syntax must be called within a with block"sv, x); | 6363 | throw CompileError("short dot/colon/indexing syntax must be called within a with block"sv, x); |
6089 | } else { | 6364 | } else { |
6090 | temp.push_back(_withVars.top()); | 6365 | temp.push_back(_withVars.top()); |
6091 | } | 6366 | } |
@@ -6231,6 +6506,93 @@ private: | |||
6231 | } | 6506 | } |
6232 | return; | 6507 | return; |
6233 | } | 6508 | } |
6509 | break; | ||
6510 | } | ||
6511 | case id<ReversedIndex_t>(): { | ||
6512 | auto rIndex = static_cast<ReversedIndex_t*>(*it); | ||
6513 | auto current = it; | ||
6514 | auto prevChain = x->new_ptr<ChainValue_t>(); | ||
6515 | for (auto i = chainList.begin(); i != current; ++i) { | ||
6516 | prevChain->items.push_back(*i); | ||
6517 | } | ||
6518 | auto var = singleVariableFrom(prevChain, AccessType::None); | ||
6519 | if (!var.empty() && isLocal(var)) { | ||
6520 | auto indexNode = toAst<Exp_t>('#' + var, rIndex); | ||
6521 | if (rIndex->modifier) { | ||
6522 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
6523 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
6524 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
6525 | indexNode->opValues.push_back(opValue); | ||
6526 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
6527 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
6528 | } | ||
6529 | prevChain->items.push_back(indexNode); | ||
6530 | auto next = current; | ||
6531 | ++next; | ||
6532 | for (auto i = next; i != chainList.end(); ++i) { | ||
6533 | prevChain->items.push_back(*i); | ||
6534 | } | ||
6535 | if (usage == ExpUsage::Assignment) { | ||
6536 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
6537 | assignment->expList.set(assignList); | ||
6538 | auto assign = x->new_ptr<Assign_t>(); | ||
6539 | assign->values.push_back(newExp(prevChain, x)); | ||
6540 | assignment->action.set(assign); | ||
6541 | transformAssignment(assignment, out); | ||
6542 | return; | ||
6543 | } | ||
6544 | transformChainValue(prevChain, out, usage, assignList); | ||
6545 | return; | ||
6546 | } else { | ||
6547 | auto itemVar = getUnusedName("_item_"sv); | ||
6548 | auto asmt = assignmentFrom(toAst<Exp_t>(itemVar, x), newExp(prevChain, x), x); | ||
6549 | auto stmt1 = x->new_ptr<Statement_t>(); | ||
6550 | stmt1->content.set(asmt); | ||
6551 | auto newChain = x->new_ptr<ChainValue_t>(); | ||
6552 | newChain->items.push_back(toAst<Callable_t>(itemVar, x)); | ||
6553 | auto indexNode = toAst<Exp_t>('#' + itemVar, rIndex); | ||
6554 | if (rIndex->modifier) { | ||
6555 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
6556 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
6557 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
6558 | indexNode->opValues.push_back(opValue); | ||
6559 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
6560 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
6561 | } | ||
6562 | newChain->items.push_back(indexNode); | ||
6563 | auto next = current; | ||
6564 | ++next; | ||
6565 | for (auto i = next; i != chainList.end(); ++i) { | ||
6566 | newChain->items.push_back(*i); | ||
6567 | } | ||
6568 | auto expList = x->new_ptr<ExpList_t>(); | ||
6569 | expList->exprs.push_back(newExp(newChain, x)); | ||
6570 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
6571 | expListAssign->expList.set(expList); | ||
6572 | auto stmt2 = x->new_ptr<Statement_t>(); | ||
6573 | stmt2->content.set(expListAssign); | ||
6574 | auto block = x->new_ptr<Block_t>(); | ||
6575 | block->statements.push_back(stmt1); | ||
6576 | block->statements.push_back(stmt2); | ||
6577 | auto body = x->new_ptr<Body_t>(); | ||
6578 | body->content.set(block); | ||
6579 | auto doNode = x->new_ptr<Do_t>(); | ||
6580 | doNode->body.set(body); | ||
6581 | if (usage == ExpUsage::Assignment) { | ||
6582 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
6583 | assignment->expList.set(assignList); | ||
6584 | auto assign = x->new_ptr<Assign_t>(); | ||
6585 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
6586 | sVal->value.set(doNode); | ||
6587 | assign->values.push_back(newExp(sVal, x)); | ||
6588 | assignment->action.set(assign); | ||
6589 | transformAssignment(assignment, out); | ||
6590 | return; | ||
6591 | } | ||
6592 | transformDo(doNode, out, usage); | ||
6593 | return; | ||
6594 | } | ||
6595 | break; | ||
6234 | } | 6596 | } |
6235 | } | 6597 | } |
6236 | } | 6598 | } |
@@ -6415,7 +6777,7 @@ private: | |||
6415 | } | 6777 | } |
6416 | } | 6778 | } |
6417 | } | 6779 | } |
6418 | int len = lua_objlen(L, -1); | 6780 | int len = static_cast<int>(lua_objlen(L, -1)); |
6419 | lua_pushnil(L); // cur nil | 6781 | lua_pushnil(L); // cur nil |
6420 | for (int i = len; i >= 1; i--) { | 6782 | for (int i = len; i >= 1; i--) { |
6421 | lua_pop(L, 1); // cur | 6783 | lua_pop(L, 1); // cur |
@@ -6427,7 +6789,25 @@ private: | |||
6427 | break; | 6789 | break; |
6428 | } | 6790 | } |
6429 | } | 6791 | } |
6430 | if (!lua_isfunction(L, -1)) { | 6792 | str_list checks; |
6793 | if (lua_istable(L, -1)) { | ||
6794 | lua_rawgeti(L, -1, 1); // cur macrotab checks | ||
6795 | int len = static_cast<int>(lua_objlen(L, -1)); | ||
6796 | for (int i = 1; i <= len; i++) { | ||
6797 | lua_rawgeti(L, -1, i); | ||
6798 | if (lua_toboolean(L, -1) == 0) { | ||
6799 | checks.emplace_back(); | ||
6800 | } else { | ||
6801 | size_t str_len = 0; | ||
6802 | auto str = lua_tolstring(L, -1, &str_len); | ||
6803 | checks.emplace_back(std::string{str, str_len}); | ||
6804 | } | ||
6805 | lua_pop(L, 1); | ||
6806 | } | ||
6807 | lua_pop(L, 1); | ||
6808 | lua_rawgeti(L, -1, 2); // cur macrotab macroFunc | ||
6809 | lua_remove(L, -2); // cur macroFunc | ||
6810 | } else if (!lua_isfunction(L, -1)) { | ||
6431 | auto code = expandBuiltinMacro(macroName, x); | 6811 | auto code = expandBuiltinMacro(macroName, x); |
6432 | if (!code.empty()) return code; | 6812 | if (!code.empty()) return code; |
6433 | if (macroName == "is_ast"sv) { | 6813 | if (macroName == "is_ast"sv) { |
@@ -6472,11 +6852,34 @@ private: | |||
6472 | } // cur macroFunc | 6852 | } // cur macroFunc |
6473 | pushYue("pcall"sv); // cur macroFunc pcall | 6853 | pushYue("pcall"sv); // cur macroFunc pcall |
6474 | lua_insert(L, -2); // cur pcall macroFunc | 6854 | lua_insert(L, -2); // cur pcall macroFunc |
6475 | if (!lua_checkstack(L, argStrs.size())) { | 6855 | if (!lua_checkstack(L, static_cast<int>(argStrs.size()))) { |
6476 | throw CompileError("too much macro params"s, x); | 6856 | throw CompileError("too much macro params"s, x); |
6477 | } | 6857 | } |
6858 | auto checkIt = checks.begin(); | ||
6859 | node_container::const_iterator argIt; | ||
6860 | if (args) { | ||
6861 | argIt = args->begin(); | ||
6862 | } | ||
6478 | for (const auto& arg : argStrs) { | 6863 | for (const auto& arg : argStrs) { |
6864 | if (checkIt != checks.end()) { | ||
6865 | if (checkIt->empty()) { | ||
6866 | ++checkIt; | ||
6867 | } else { | ||
6868 | if ((*checkIt)[0] == '.') { | ||
6869 | auto astName = checkIt->substr(3); | ||
6870 | if (!_parser.match(astName, arg)) { | ||
6871 | throw CompileError("expecting \""s + astName + "\", AST mismatch"s, *argIt); | ||
6872 | } | ||
6873 | } else { | ||
6874 | if (!_parser.match(*checkIt, arg)) { | ||
6875 | throw CompileError("expecting \""s + *checkIt + "\", AST mismatch"s, *argIt); | ||
6876 | } | ||
6877 | ++checkIt; | ||
6878 | } | ||
6879 | } | ||
6880 | } | ||
6479 | lua_pushlstring(L, arg.c_str(), arg.size()); | 6881 | lua_pushlstring(L, arg.c_str(), arg.size()); |
6882 | ++argIt; | ||
6480 | } // cur pcall macroFunc args... | 6883 | } // cur pcall macroFunc args... |
6481 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; | 6884 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; |
6482 | if (!success) { // cur err | 6885 | if (!success) { // cur err |
@@ -6606,14 +7009,14 @@ private: | |||
6606 | } else { | 7009 | } else { |
6607 | if (!codes.empty()) { | 7010 | if (!codes.empty()) { |
6608 | if (isBlock) { | 7011 | if (isBlock) { |
6609 | info = _parser.parse<BlockEnd_t>(codes); | 7012 | info = _parser.parse<BlockEnd_t>(codes, false); |
6610 | if (info.error) { | 7013 | if (info.error) { |
6611 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); | 7014 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); |
6612 | } | 7015 | } |
6613 | } else { | 7016 | } else { |
6614 | info = _parser.parse<Exp_t>(codes); | 7017 | info = _parser.parse<Exp_t>(codes, false); |
6615 | if (!info.node && allowBlockMacroReturn) { | 7018 | if (!info.node && allowBlockMacroReturn) { |
6616 | info = _parser.parse<BlockEnd_t>(codes); | 7019 | info = _parser.parse<BlockEnd_t>(codes, false); |
6617 | if (info.error) { | 7020 | if (info.error) { |
6618 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); | 7021 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); |
6619 | } | 7022 | } |
@@ -6749,6 +7152,9 @@ private: | |||
6749 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | 7152 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { |
6750 | return; | 7153 | return; |
6751 | } | 7154 | } |
7155 | if (transformChainEndWithSlice(chainList, out, usage, assignList)) { | ||
7156 | return; | ||
7157 | } | ||
6752 | transformChainList(chainList, out, usage, assignList); | 7158 | transformChainList(chainList, out, usage, assignList); |
6753 | } | 7159 | } |
6754 | 7160 | ||
@@ -7144,6 +7550,33 @@ private: | |||
7144 | void transformNum(Num_t* num, str_list& out) { | 7550 | void transformNum(Num_t* num, str_list& out) { |
7145 | std::string numStr = _parser.toString(num); | 7551 | std::string numStr = _parser.toString(num); |
7146 | numStr.erase(std::remove(numStr.begin(), numStr.end(), '_'), numStr.end()); | 7552 | numStr.erase(std::remove(numStr.begin(), numStr.end(), '_'), numStr.end()); |
7553 | if (numStr.size() > 2 && numStr[0] == '0') { | ||
7554 | if (numStr[1] == 'b' || numStr[1] == 'B') { | ||
7555 | std::string binaryPart = numStr.substr(2); | ||
7556 | try { | ||
7557 | unsigned long long value = std::stoull(binaryPart, nullptr, 2); | ||
7558 | numStr = std::to_string(value); | ||
7559 | } catch (const std::exception&) { | ||
7560 | throw CompileError("invalid binary literal"sv, num); | ||
7561 | } | ||
7562 | } else if (getLuaTarget(num) < 502) { | ||
7563 | if (numStr[1] == 'x' || numStr[1] == 'X') { | ||
7564 | if (numStr.find_first_of(".-"sv) != std::string::npos) { | ||
7565 | std::stringstream ss(numStr); | ||
7566 | double v; | ||
7567 | ss >> std::hexfloat >> v; | ||
7568 | if (ss.fail() || !std::isfinite(v)) { | ||
7569 | throw CompileError("invalid hexβfloat literal"sv, num); | ||
7570 | } | ||
7571 | std::ostringstream outSs; | ||
7572 | outSs << std::setprecision(17) << v; | ||
7573 | numStr = outSs.str(); | ||
7574 | } else { | ||
7575 | numStr.erase(std::remove(numStr.begin(), numStr.end(), '+'), numStr.end()); | ||
7576 | } | ||
7577 | } | ||
7578 | } | ||
7579 | } | ||
7147 | out.push_back(numStr); | 7580 | out.push_back(numStr); |
7148 | } | 7581 | } |
7149 | 7582 | ||
@@ -7829,6 +8262,11 @@ private: | |||
7829 | } | 8262 | } |
7830 | 8263 | ||
7831 | bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { | 8264 | bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { |
8265 | enum class NumState { | ||
8266 | Unknown, | ||
8267 | Positive, | ||
8268 | Negtive | ||
8269 | }; | ||
7832 | auto x = nameList; | 8270 | auto x = nameList; |
7833 | str_list temp; | 8271 | str_list temp; |
7834 | str_list vars; | 8272 | str_list vars; |
@@ -7895,15 +8333,35 @@ private: | |||
7895 | for (auto item : chainList) { | 8333 | for (auto item : chainList) { |
7896 | chain->items.push_back(item); | 8334 | chain->items.push_back(item); |
7897 | } | 8335 | } |
7898 | std::string startValue("1"sv); | 8336 | std::string startValue; |
8337 | NumState startStatus = NumState::Unknown; | ||
7899 | if (auto exp = slice->startValue.as<Exp_t>()) { | 8338 | if (auto exp = slice->startValue.as<Exp_t>()) { |
7900 | transformExp(exp, temp, ExpUsage::Closure); | 8339 | transformExp(exp, temp, ExpUsage::Closure); |
8340 | if (temp.back().at(0) == '-') { | ||
8341 | if (_parser.match<Num_t>(temp.back().substr(1))) { | ||
8342 | startStatus = NumState::Negtive; | ||
8343 | } | ||
8344 | } else { | ||
8345 | if (_parser.match<Num_t>(temp.back())) { | ||
8346 | startStatus = NumState::Positive; | ||
8347 | } | ||
8348 | } | ||
7901 | startValue = std::move(temp.back()); | 8349 | startValue = std::move(temp.back()); |
7902 | temp.pop_back(); | 8350 | temp.pop_back(); |
7903 | } | 8351 | } |
7904 | std::string stopValue; | 8352 | std::string stopValue; |
8353 | NumState stopStatus = NumState::Unknown; | ||
7905 | if (auto exp = slice->stopValue.as<Exp_t>()) { | 8354 | if (auto exp = slice->stopValue.as<Exp_t>()) { |
7906 | transformExp(exp, temp, ExpUsage::Closure); | 8355 | transformExp(exp, temp, ExpUsage::Closure); |
8356 | if (temp.back().at(0) == '-') { | ||
8357 | if (_parser.match<Num_t>(temp.back().substr(1))) { | ||
8358 | stopStatus = NumState::Negtive; | ||
8359 | } | ||
8360 | } else { | ||
8361 | if (_parser.match<Num_t>(temp.back())) { | ||
8362 | stopStatus = NumState::Positive; | ||
8363 | } | ||
8364 | } | ||
7907 | stopValue = std::move(temp.back()); | 8365 | stopValue = std::move(temp.back()); |
7908 | temp.pop_back(); | 8366 | temp.pop_back(); |
7909 | } | 8367 | } |
@@ -7925,8 +8383,33 @@ private: | |||
7925 | transformChainValue(chain, temp, ExpUsage::Closure); | 8383 | transformChainValue(chain, temp, ExpUsage::Closure); |
7926 | _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); | 8384 | _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); |
7927 | } | 8385 | } |
8386 | if (startValue.empty()) { | ||
8387 | startValue = "1"s; | ||
8388 | startStatus = NumState::Positive; | ||
8389 | } | ||
8390 | std::string minVar; | ||
8391 | if (startStatus != NumState::Positive) { | ||
8392 | std::string prefix; | ||
8393 | if (!extraScope && !inClosure && needScope) { | ||
8394 | extraScope = true; | ||
8395 | prefix = indent() + "do"s + nll(x); | ||
8396 | pushScope(); | ||
8397 | } | ||
8398 | minVar = getUnusedName("_min_"sv); | ||
8399 | varBefore.push_back(minVar); | ||
8400 | if (startStatus == NumState::Negtive) { | ||
8401 | _buf << prefix << indent() << "local "sv << minVar << " = "sv << "#"sv << listVar << " + "sv << startValue << " + 1"sv << nll(nameList); | ||
8402 | } else { | ||
8403 | _buf << prefix << indent() << "local "sv << minVar << " = "sv << startValue << nll(nameList); | ||
8404 | } | ||
8405 | } | ||
8406 | bool defaultStop = false; | ||
8407 | if (stopValue.empty()) { | ||
8408 | stopValue = "#"s + listVar; | ||
8409 | defaultStop = true; | ||
8410 | } | ||
7928 | std::string maxVar; | 8411 | std::string maxVar; |
7929 | if (!stopValue.empty()) { | 8412 | if (stopStatus != NumState::Positive) { |
7930 | std::string prefix; | 8413 | std::string prefix; |
7931 | if (!extraScope && !inClosure && needScope) { | 8414 | if (!extraScope && !inClosure && needScope) { |
7932 | extraScope = true; | 8415 | extraScope = true; |
@@ -7935,14 +8418,45 @@ private: | |||
7935 | } | 8418 | } |
7936 | maxVar = getUnusedName("_max_"sv); | 8419 | maxVar = getUnusedName("_max_"sv); |
7937 | varBefore.push_back(maxVar); | 8420 | varBefore.push_back(maxVar); |
7938 | _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); | 8421 | if (stopStatus == NumState::Negtive) { |
8422 | _buf << indent() << "local "sv << maxVar << " = "sv << "#"sv << listVar << " + "sv << stopValue << " + 1"sv << nll(nameList); | ||
8423 | } else { | ||
8424 | _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); | ||
8425 | } | ||
8426 | } | ||
8427 | if (startStatus == NumState::Unknown) { | ||
8428 | _buf << indent() << minVar << " = "sv << minVar << " < 0 and #"sv << listVar << " + "sv << minVar << " + 1 or "sv << minVar << nll(nameList); | ||
8429 | } | ||
8430 | if (!defaultStop && stopStatus == NumState::Unknown) { | ||
8431 | _buf << indent() << maxVar << " = "sv << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " + 1 or "sv << maxVar << nll(nameList); | ||
7939 | } | 8432 | } |
7940 | _buf << indent() << "for "sv << indexVar << " = "sv; | 8433 | _buf << indent() << "for "sv << indexVar << " = "sv; |
7941 | _buf << startValue << ", "sv; | 8434 | if (startValue.empty()) { |
8435 | _buf << "1"sv; | ||
8436 | } else { | ||
8437 | switch (startStatus) { | ||
8438 | case NumState::Unknown: | ||
8439 | case NumState::Negtive: | ||
8440 | _buf << minVar; | ||
8441 | break; | ||
8442 | case NumState::Positive: | ||
8443 | _buf << startValue; | ||
8444 | break; | ||
8445 | } | ||
8446 | } | ||
8447 | _buf << ", "sv; | ||
7942 | if (stopValue.empty()) { | 8448 | if (stopValue.empty()) { |
7943 | _buf << "#"sv << listVar; | 8449 | _buf << "#"sv << listVar; |
7944 | } else { | 8450 | } else { |
7945 | _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " or "sv << maxVar; | 8451 | switch (stopStatus) { |
8452 | case NumState::Unknown: | ||
8453 | case NumState::Negtive: | ||
8454 | _buf << maxVar; | ||
8455 | break; | ||
8456 | case NumState::Positive: | ||
8457 | _buf << stopValue; | ||
8458 | break; | ||
8459 | } | ||
7946 | } | 8460 | } |
7947 | if (!stepValue.empty()) { | 8461 | if (!stepValue.empty()) { |
7948 | _buf << ", "sv << stepValue; | 8462 | _buf << ", "sv << stepValue; |
@@ -7982,7 +8496,7 @@ private: | |||
7982 | pushScope(); | 8496 | pushScope(); |
7983 | for (const auto& var : vars) forceAddToScope(var); | 8497 | for (const auto& var : vars) forceAddToScope(var); |
7984 | for (const auto& var : varAfter) addToScope(var); | 8498 | for (const auto& var : varAfter) addToScope(var); |
7985 | if (!varConstAfter.empty()) markVarConst(varConstAfter); | 8499 | if (!varConstAfter.empty()) markVarLocalConst(varConstAfter); |
7986 | if (!destructPairs.empty()) { | 8500 | if (!destructPairs.empty()) { |
7987 | temp.clear(); | 8501 | temp.clear(); |
7988 | for (auto& pair : destructPairs) { | 8502 | for (auto& pair : destructPairs) { |
@@ -8067,7 +8581,7 @@ private: | |||
8067 | _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : ", "s + step) << " do"sv << nll(var); | 8581 | _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : ", "s + step) << " do"sv << nll(var); |
8068 | pushScope(); | 8582 | pushScope(); |
8069 | forceAddToScope(varName); | 8583 | forceAddToScope(varName); |
8070 | markVarConst(varName); | 8584 | markVarLocalConst(varName); |
8071 | out.push_back(clearBuf()); | 8585 | out.push_back(clearBuf()); |
8072 | } | 8586 | } |
8073 | 8587 | ||
@@ -8075,26 +8589,59 @@ private: | |||
8075 | transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); | 8589 | transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); |
8076 | } | 8590 | } |
8077 | 8591 | ||
8078 | void transform_plain_body(ast_node* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8592 | void transform_plain_body(ast_node* bodyOrStmt, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
8079 | switch (body->get_id()) { | 8593 | switch (bodyOrStmt->get_id()) { |
8080 | case id<Block_t>(): | 8594 | case id<Block_t>(): |
8081 | transformBlock(static_cast<Block_t*>(body), out, usage, assignList); | 8595 | transformBlock(static_cast<Block_t*>(bodyOrStmt), out, usage, assignList); |
8082 | break; | 8596 | break; |
8083 | case id<Statement_t>(): { | 8597 | case id<Statement_t>(): { |
8084 | auto newBlock = body->new_ptr<Block_t>(); | 8598 | auto newBlock = bodyOrStmt->new_ptr<Block_t>(); |
8085 | newBlock->statements.push_back(body); | 8599 | newBlock->statements.push_back(bodyOrStmt); |
8086 | transformBlock(newBlock, out, usage, assignList); | 8600 | transformBlock(newBlock, out, usage, assignList); |
8087 | break; | 8601 | break; |
8088 | } | 8602 | } |
8089 | default: YUEE("AST node mismatch", body); break; | 8603 | default: YUEE("AST node mismatch", bodyOrStmt); break; |
8090 | } | 8604 | } |
8091 | } | 8605 | } |
8092 | 8606 | ||
8093 | bool hasContinueStatement(ast_node* body) { | 8607 | enum class BreakLoopType { |
8094 | return traversal::Stop == body->traverse([&](ast_node* node) { | 8608 | None = 0, |
8609 | Break = 1, | ||
8610 | BreakWithValue = 1 << 1, | ||
8611 | Continue = 1 << 2 | ||
8612 | }; | ||
8613 | |||
8614 | bool hasBreak(uint32_t breakLoopType) const { | ||
8615 | return (breakLoopType & int(BreakLoopType::Break)) != 0; | ||
8616 | } | ||
8617 | |||
8618 | bool hasBreakWithValue(uint32_t breakLoopType) const { | ||
8619 | return (breakLoopType & int(BreakLoopType::BreakWithValue)) != 0; | ||
8620 | } | ||
8621 | |||
8622 | bool hasContinue(uint32_t breakLoopType) const { | ||
8623 | return (breakLoopType & int(BreakLoopType::Continue)) != 0; | ||
8624 | } | ||
8625 | |||
8626 | uint32_t getBreakLoopType(ast_node* body, const std::string& varBWV) { | ||
8627 | uint32_t type = 0; | ||
8628 | body->traverse([&](ast_node* node) { | ||
8095 | if (auto stmt = ast_cast<Statement_t>(node)) { | 8629 | if (auto stmt = ast_cast<Statement_t>(node)) { |
8096 | if (stmt->content.is<BreakLoop_t>()) { | 8630 | if (auto breakLoop = stmt->content.as<BreakLoop_t>()) { |
8097 | return _parser.toString(stmt->content) == "continue"sv ? traversal::Stop : traversal::Return; | 8631 | if (breakLoop->type.is<Continue_t>()) { |
8632 | type |= int(BreakLoopType::Continue); | ||
8633 | return traversal::Return; | ||
8634 | } else { | ||
8635 | if (breakLoop->value) { | ||
8636 | if (varBWV.empty()) { | ||
8637 | throw CompileError("break with a value is not allowed here"sv, breakLoop->value); | ||
8638 | } | ||
8639 | type |= int(BreakLoopType::BreakWithValue); | ||
8640 | breakLoop->varBWV = varBWV; | ||
8641 | } else { | ||
8642 | type |= int(BreakLoopType::Break); | ||
8643 | } | ||
8644 | } | ||
8098 | } else if (auto expList = expListFrom(stmt)) { | 8645 | } else if (auto expList = expListFrom(stmt)) { |
8099 | BLOCK_START | 8646 | BLOCK_START |
8100 | auto value = singleValueFrom(expList); | 8647 | auto value = singleValueFrom(expList); |
@@ -8105,40 +8652,30 @@ private: | |||
8105 | switch (sVal->get_id()) { | 8652 | switch (sVal->get_id()) { |
8106 | case id<With_t>(): { | 8653 | case id<With_t>(): { |
8107 | auto withNode = static_cast<With_t*>(sVal); | 8654 | auto withNode = static_cast<With_t*>(sVal); |
8108 | if (hasContinueStatement(withNode->body)) { | 8655 | type |= getBreakLoopType(withNode->body, varBWV); |
8109 | return traversal::Stop; | 8656 | return traversal::Return; |
8110 | } | ||
8111 | break; | ||
8112 | } | 8657 | } |
8113 | case id<Do_t>(): { | 8658 | case id<Do_t>(): { |
8114 | auto doNode = static_cast<Do_t*>(sVal); | 8659 | auto doNode = static_cast<Do_t*>(sVal); |
8115 | if (hasContinueStatement(doNode->body)) { | 8660 | type |= getBreakLoopType(doNode->body, varBWV); |
8116 | return traversal::Stop; | 8661 | return traversal::Return; |
8117 | } | ||
8118 | break; | ||
8119 | } | 8662 | } |
8120 | case id<If_t>(): { | 8663 | case id<If_t>(): { |
8121 | auto ifNode = static_cast<If_t*>(sVal); | 8664 | auto ifNode = static_cast<If_t*>(sVal); |
8122 | for (auto n : ifNode->nodes.objects()) { | 8665 | for (auto n : ifNode->nodes.objects()) { |
8123 | if (hasContinueStatement(n)) { | 8666 | type |= getBreakLoopType(n, varBWV); |
8124 | return traversal::Stop; | ||
8125 | } | ||
8126 | } | 8667 | } |
8127 | break; | 8668 | return traversal::Return; |
8128 | } | 8669 | } |
8129 | case id<Switch_t>(): { | 8670 | case id<Switch_t>(): { |
8130 | auto switchNode = static_cast<Switch_t*>(sVal); | 8671 | auto switchNode = static_cast<Switch_t*>(sVal); |
8131 | for (auto branch : switchNode->branches.objects()) { | 8672 | for (auto branch : switchNode->branches.objects()) { |
8132 | if (hasContinueStatement(static_cast<SwitchCase_t*>(branch)->body)) { | 8673 | type |= getBreakLoopType(static_cast<SwitchCase_t*>(branch)->body, varBWV); |
8133 | return traversal::Stop; | ||
8134 | } | ||
8135 | } | 8674 | } |
8136 | if (switchNode->lastBranch) { | 8675 | if (switchNode->lastBranch) { |
8137 | if (hasContinueStatement(switchNode->lastBranch)) { | 8676 | type |= getBreakLoopType(switchNode->lastBranch, varBWV); |
8138 | return traversal::Stop; | ||
8139 | } | ||
8140 | } | 8677 | } |
8141 | break; | 8678 | return traversal::Return; |
8142 | } | 8679 | } |
8143 | } | 8680 | } |
8144 | BLOCK_END | 8681 | BLOCK_END |
@@ -8152,6 +8689,7 @@ private: | |||
8152 | } | 8689 | } |
8153 | return traversal::Return; | 8690 | return traversal::Return; |
8154 | }); | 8691 | }); |
8692 | return type; | ||
8155 | } | 8693 | } |
8156 | 8694 | ||
8157 | void addDoToLastLineReturn(ast_node* body) { | 8695 | void addDoToLastLineReturn(ast_node* body) { |
@@ -8175,10 +8713,10 @@ private: | |||
8175 | } | 8713 | } |
8176 | } | 8714 | } |
8177 | 8715 | ||
8178 | void transformLoopBody(ast_node* body, str_list& out, const std::string& appendContent, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8716 | void transformLoopBody(ast_node* body, str_list& out, uint32_t breakLoopType, ExpUsage usage, ExpList_t* assignList = nullptr) { |
8179 | str_list temp; | 8717 | str_list temp; |
8180 | bool extraDo = false; | 8718 | bool extraDo = false; |
8181 | bool withContinue = hasContinueStatement(body); | 8719 | bool withContinue = hasContinue(breakLoopType); |
8182 | int target = getLuaTarget(body); | 8720 | int target = getLuaTarget(body); |
8183 | std::string extraLabel; | 8721 | std::string extraLabel; |
8184 | if (withContinue) { | 8722 | if (withContinue) { |
@@ -8187,7 +8725,7 @@ private: | |||
8187 | if (!block->statements.empty()) { | 8725 | if (!block->statements.empty()) { |
8188 | auto stmt = static_cast<Statement_t*>(block->statements.back()); | 8726 | auto stmt = static_cast<Statement_t*>(block->statements.back()); |
8189 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { | 8727 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { |
8190 | extraDo = _parser.toString(breakLoop) == "break"sv; | 8728 | extraDo = breakLoop->type.is<Break_t>(); |
8191 | } | 8729 | } |
8192 | } | 8730 | } |
8193 | } | 8731 | } |
@@ -8220,9 +8758,6 @@ private: | |||
8220 | popScope(); | 8758 | popScope(); |
8221 | _buf << indent() << "end"sv << nll(body); | 8759 | _buf << indent() << "end"sv << nll(body); |
8222 | } | 8760 | } |
8223 | if (!appendContent.empty()) { | ||
8224 | _buf << indent() << appendContent; | ||
8225 | } | ||
8226 | _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); | 8761 | _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); |
8227 | popScope(); | 8762 | popScope(); |
8228 | _buf << indent() << "until true"sv << nlr(body); | 8763 | _buf << indent() << "until true"sv << nlr(body); |
@@ -8232,14 +8767,9 @@ private: | |||
8232 | temp.push_back(clearBuf()); | 8767 | temp.push_back(clearBuf()); |
8233 | _continueVars.pop(); | 8768 | _continueVars.pop(); |
8234 | } else { | 8769 | } else { |
8235 | if (!appendContent.empty()) { | ||
8236 | temp.push_back(indent() + appendContent); | ||
8237 | } | ||
8238 | temp.push_back(extraLabel); | 8770 | temp.push_back(extraLabel); |
8239 | _continueVars.pop(); | 8771 | _continueVars.pop(); |
8240 | } | 8772 | } |
8241 | } else if (!appendContent.empty()) { | ||
8242 | temp.back().append(indent() + appendContent); | ||
8243 | } | 8773 | } |
8244 | out.push_back(join(temp)); | 8774 | out.push_back(join(temp)); |
8245 | } | 8775 | } |
@@ -8247,8 +8777,9 @@ private: | |||
8247 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { | 8777 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { |
8248 | str_list temp; | 8778 | str_list temp; |
8249 | bool extraDo = false; | 8779 | bool extraDo = false; |
8250 | auto body = repeatNode->body->content.get(); | 8780 | auto body = repeatNode->body.get(); |
8251 | bool withContinue = hasContinueStatement(body); | 8781 | auto breakLoopType = getBreakLoopType(body, Empty); |
8782 | bool withContinue = hasContinue(breakLoopType); | ||
8252 | std::string conditionVar; | 8783 | std::string conditionVar; |
8253 | std::string extraLabel; | 8784 | std::string extraLabel; |
8254 | ast_ptr<false, ExpListAssign_t> condAssign; | 8785 | ast_ptr<false, ExpListAssign_t> condAssign; |
@@ -8259,7 +8790,7 @@ private: | |||
8259 | if (!block->statements.empty()) { | 8790 | if (!block->statements.empty()) { |
8260 | auto stmt = static_cast<Statement_t*>(block->statements.back()); | 8791 | auto stmt = static_cast<Statement_t*>(block->statements.back()); |
8261 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { | 8792 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { |
8262 | extraDo = _parser.toString(breakLoop) == "break"sv; | 8793 | extraDo = breakLoop->type.is<Break_t>(); |
8263 | } | 8794 | } |
8264 | } | 8795 | } |
8265 | } | 8796 | } |
@@ -8322,7 +8853,8 @@ private: | |||
8322 | void transformFor(For_t* forNode, str_list& out) { | 8853 | void transformFor(For_t* forNode, str_list& out) { |
8323 | str_list temp; | 8854 | str_list temp; |
8324 | transformForHead(forNode, temp); | 8855 | transformForHead(forNode, temp); |
8325 | transformLoopBody(forNode->body, temp, Empty, ExpUsage::Common); | 8856 | auto breakLoopType = getBreakLoopType(forNode->body, Empty); |
8857 | transformLoopBody(forNode->body, temp, breakLoopType, ExpUsage::Common); | ||
8326 | popScope(); | 8858 | popScope(); |
8327 | out.push_back(join(temp) + indent() + "end"s + nlr(forNode)); | 8859 | out.push_back(join(temp) + indent() + "end"s + nlr(forNode)); |
8328 | } | 8860 | } |
@@ -8333,13 +8865,24 @@ private: | |||
8333 | addToScope(accum); | 8865 | addToScope(accum); |
8334 | std::string len = getUnusedName("_len_"sv); | 8866 | std::string len = getUnusedName("_len_"sv); |
8335 | addToScope(len); | 8867 | addToScope(len); |
8336 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forNode); | 8868 | auto breakLoopType = getBreakLoopType(forNode->body, accum); |
8869 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(forNode); | ||
8870 | out.emplace_back(clearBuf()); | ||
8337 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); | 8871 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); |
8338 | out.push_back(clearBuf()); | 8872 | auto& lenAssign = out.emplace_back(clearBuf()); |
8339 | transformForHead(forNode, out); | 8873 | transformForHead(forNode, out); |
8340 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 8874 | if (hasBreakWithValue(breakLoopType)) { |
8341 | auto lenLine = len + " = "s + len + " + 1"s + nlr(forNode->body); | 8875 | lenAssign.clear(); |
8342 | transformLoopBody(forNode->body, out, lenLine, ExpUsage::Assignment, expList); | 8876 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Common); |
8877 | } else { | ||
8878 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | ||
8879 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forNode->body); | ||
8880 | expList->followStmt = followStmt.get(); | ||
8881 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
8882 | if (!expList->followStmtProcessed) { | ||
8883 | lenAssign.clear(); | ||
8884 | } | ||
8885 | } | ||
8343 | popScope(); | 8886 | popScope(); |
8344 | out.push_back(indent() + "end"s + nlr(forNode)); | 8887 | out.push_back(indent() + "end"s + nlr(forNode)); |
8345 | return accum; | 8888 | return accum; |
@@ -8418,7 +8961,8 @@ private: | |||
8418 | void transformForEach(ForEach_t* forEach, str_list& out) { | 8961 | void transformForEach(ForEach_t* forEach, str_list& out) { |
8419 | str_list temp; | 8962 | str_list temp; |
8420 | bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false); | 8963 | bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false); |
8421 | transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common); | 8964 | auto breakLoopType = getBreakLoopType(forEach->body, Empty); |
8965 | transformLoopBody(forEach->body, temp, breakLoopType, ExpUsage::Common); | ||
8422 | popScope(); | 8966 | popScope(); |
8423 | out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach)); | 8967 | out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach)); |
8424 | if (extraScoped) { | 8968 | if (extraScoped) { |
@@ -8433,13 +8977,24 @@ private: | |||
8433 | addToScope(accum); | 8977 | addToScope(accum); |
8434 | std::string len = getUnusedName("_len_"sv); | 8978 | std::string len = getUnusedName("_len_"sv); |
8435 | addToScope(len); | 8979 | addToScope(len); |
8436 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); | 8980 | auto breakLoopType = getBreakLoopType(forEach->body, accum); |
8981 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(forEach); | ||
8982 | out.emplace_back(clearBuf()); | ||
8437 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); | 8983 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); |
8438 | out.push_back(clearBuf()); | 8984 | auto& lenAssign = out.emplace_back(clearBuf()); |
8439 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); | 8985 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); |
8440 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 8986 | if (hasBreakWithValue(breakLoopType)) { |
8441 | auto lenLine = len + " = "s + len + " + 1"s + nlr(forEach->body); | 8987 | lenAssign.clear(); |
8442 | transformLoopBody(forEach->body, out, lenLine, ExpUsage::Assignment, expList); | 8988 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Common); |
8989 | } else { | ||
8990 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | ||
8991 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forEach->body); | ||
8992 | expList->followStmt = followStmt.get(); | ||
8993 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
8994 | if (!expList->followStmtProcessed) { | ||
8995 | lenAssign.clear(); | ||
8996 | } | ||
8997 | } | ||
8443 | popScope(); | 8998 | popScope(); |
8444 | out.push_back(indent() + "end"s + nlr(forEach)); | 8999 | out.push_back(indent() + "end"s + nlr(forEach)); |
8445 | return accum; | 9000 | return accum; |
@@ -8623,12 +9178,64 @@ private: | |||
8623 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); | 9178 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); |
8624 | } | 9179 | } |
8625 | 9180 | ||
9181 | void transformYAMLMultiline(YAMLMultiline_t* multiline, str_list& out) { | ||
9182 | std::optional<std::string> indent; | ||
9183 | str_list temp; | ||
9184 | for (auto line_ : multiline->lines.objects()) { | ||
9185 | auto line = static_cast<YAMLLine_t*>(line_); | ||
9186 | auto indentStr = _parser.toString(line->indent); | ||
9187 | if (!indent) { | ||
9188 | indent = indentStr; | ||
9189 | } | ||
9190 | if (std::string_view{indentStr.c_str(), indent.value().size()} != indent.value()) { | ||
9191 | throw CompileError("inconsistent indent"sv, line); | ||
9192 | } | ||
9193 | indentStr = indentStr.substr(indent.value().size()); | ||
9194 | str_list segs; | ||
9195 | bool firstSeg = true; | ||
9196 | for (auto seg_ : line->segments.objects()) { | ||
9197 | auto content = static_cast<YAMLLineContent_t*>(seg_)->content.get(); | ||
9198 | switch (content->get_id()) { | ||
9199 | case id<YAMLLineInner_t>(): { | ||
9200 | auto seqStr = _parser.toString(content); | ||
9201 | Utils::replace(seqStr, "\\#"sv, "#"sv); | ||
9202 | if (firstSeg) { | ||
9203 | firstSeg = false; | ||
9204 | seqStr.insert(0, indentStr); | ||
9205 | } | ||
9206 | segs.push_back(Utils::toLuaDoubleString(seqStr)); | ||
9207 | break; | ||
9208 | } | ||
9209 | case id<Exp_t>(): { | ||
9210 | if (firstSeg) { | ||
9211 | firstSeg = false; | ||
9212 | if (!indentStr.empty()) { | ||
9213 | segs.push_back(Utils::toLuaDoubleString(indentStr)); | ||
9214 | } | ||
9215 | } | ||
9216 | transformExp(static_cast<Exp_t*>(content), segs, ExpUsage::Closure); | ||
9217 | segs.back() = globalVar("tostring"sv, content, AccessType::Read) + '(' + segs.back() + ')'; | ||
9218 | break; | ||
9219 | } | ||
9220 | default: YUEE("AST node mismatch", content); break; | ||
9221 | } | ||
9222 | } | ||
9223 | temp.push_back(join(segs, " .. "sv)); | ||
9224 | } | ||
9225 | auto str = join(temp, " .. '\\n' .. "sv); | ||
9226 | Utils::replace(str, "\" .. '\\n' .. \""sv, "\\n"sv); | ||
9227 | Utils::replace(str, "\" .. '\\n'"sv, "\\n\""sv); | ||
9228 | Utils::replace(str, "'\\n' .. \""sv, "\"\\n"sv); | ||
9229 | out.push_back(str); | ||
9230 | } | ||
9231 | |||
8626 | void transformString(String_t* string, str_list& out) { | 9232 | void transformString(String_t* string, str_list& out) { |
8627 | auto str = string->str.get(); | 9233 | auto str = string->str.get(); |
8628 | switch (str->get_id()) { | 9234 | switch (str->get_id()) { |
8629 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; | 9235 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; |
8630 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(str), out); break; | 9236 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(str), out); break; |
8631 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; | 9237 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; |
9238 | case id<YAMLMultiline_t>(): transformYAMLMultiline(static_cast<YAMLMultiline_t*>(str), out); break; | ||
8632 | default: YUEE("AST node mismatch", str); break; | 9239 | default: YUEE("AST node mismatch", str); break; |
8633 | } | 9240 | } |
8634 | } | 9241 | } |
@@ -8810,7 +9417,7 @@ private: | |||
8810 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get); | 9417 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get); |
8811 | for (const auto& name : names) { | 9418 | for (const auto& name : names) { |
8812 | forceAddToScope(name.first); | 9419 | forceAddToScope(name.first); |
8813 | markVarConst(name.first); | 9420 | markVarLocalConst(name.first); |
8814 | varDefs.push_back(name.first); | 9421 | varDefs.push_back(name.first); |
8815 | classConstVars.push_back(name.first); | 9422 | classConstVars.push_back(name.first); |
8816 | } | 9423 | } |
@@ -8824,7 +9431,7 @@ private: | |||
8824 | for (const auto& item : destruct.items) { | 9431 | for (const auto& item : destruct.items) { |
8825 | if (!item.targetVar.empty()) { | 9432 | if (!item.targetVar.empty()) { |
8826 | forceAddToScope(item.targetVar); | 9433 | forceAddToScope(item.targetVar); |
8827 | markVarConst(item.targetVar); | 9434 | markVarLocalConst(item.targetVar); |
8828 | varDefs.push_back(item.targetVar); | 9435 | varDefs.push_back(item.targetVar); |
8829 | classConstVars.push_back(item.targetVar); | 9436 | classConstVars.push_back(item.targetVar); |
8830 | } | 9437 | } |
@@ -9206,11 +9813,11 @@ private: | |||
9206 | std::string withVar; | 9813 | std::string withVar; |
9207 | bool needScope = !currentScope().lastStatement && !returnValue; | 9814 | bool needScope = !currentScope().lastStatement && !returnValue; |
9208 | bool extraScope = false; | 9815 | bool extraScope = false; |
9209 | if (with->assigns) { | 9816 | if (with->assign) { |
9210 | auto vars = getAssignVars(with); | 9817 | auto vars = getAssignVars(with); |
9211 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { | 9818 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { |
9212 | if (with->assigns->values.objects().size() == 1) { | 9819 | if (with->assign->values.objects().size() == 1) { |
9213 | auto var = singleVariableFrom(with->assigns->values.objects().front(), AccessType::Read); | 9820 | auto var = singleVariableFrom(with->assign->values.objects().front(), AccessType::Read); |
9214 | if (!var.empty() && isLocal(var)) { | 9821 | if (!var.empty() && isLocal(var)) { |
9215 | withVar = var; | 9822 | withVar = var; |
9216 | } | 9823 | } |
@@ -9220,7 +9827,7 @@ private: | |||
9220 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 9827 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
9221 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); | 9828 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); |
9222 | auto assign = x->new_ptr<Assign_t>(); | 9829 | auto assign = x->new_ptr<Assign_t>(); |
9223 | assign->values.push_back(with->assigns->values.objects().front()); | 9830 | assign->values.push_back(with->assign->values.objects().front()); |
9224 | assignment->action.set(assign); | 9831 | assignment->action.set(assign); |
9225 | if (needScope) { | 9832 | if (needScope) { |
9226 | extraScope = true; | 9833 | extraScope = true; |
@@ -9234,7 +9841,7 @@ private: | |||
9234 | auto assign = x->new_ptr<Assign_t>(); | 9841 | auto assign = x->new_ptr<Assign_t>(); |
9235 | assign->values.push_back(toAst<Exp_t>(withVar, x)); | 9842 | assign->values.push_back(toAst<Exp_t>(withVar, x)); |
9236 | bool skipFirst = true; | 9843 | bool skipFirst = true; |
9237 | for (auto value : with->assigns->values.objects()) { | 9844 | for (auto value : with->assign->values.objects()) { |
9238 | if (skipFirst) { | 9845 | if (skipFirst) { |
9239 | skipFirst = false; | 9846 | skipFirst = false; |
9240 | continue; | 9847 | continue; |
@@ -9247,7 +9854,7 @@ private: | |||
9247 | withVar = vars.front(); | 9854 | withVar = vars.front(); |
9248 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 9855 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
9249 | assignment->expList.set(with->valueList); | 9856 | assignment->expList.set(with->valueList); |
9250 | assignment->action.set(with->assigns); | 9857 | assignment->action.set(with->assign); |
9251 | if (needScope) { | 9858 | if (needScope) { |
9252 | extraScope = true; | 9859 | extraScope = true; |
9253 | temp.push_back(indent() + "do"s + nll(with)); | 9860 | temp.push_back(indent() + "do"s + nll(with)); |
@@ -9325,15 +9932,57 @@ private: | |||
9325 | } | 9932 | } |
9326 | } | 9933 | } |
9327 | _withVars.push(withVar); | 9934 | _withVars.push(withVar); |
9935 | std::string breakWithVar; | ||
9936 | if (assignList || returnValue) { | ||
9937 | auto breakLoopType = getBreakLoopType(with->body, withVar); | ||
9938 | if (hasBreakWithValue(breakLoopType)) { | ||
9939 | breakWithVar = withVar; | ||
9940 | } | ||
9941 | } | ||
9328 | if (with->eop) { | 9942 | if (with->eop) { |
9329 | auto ifNode = x->new_ptr<If_t>(); | 9943 | auto ifNode = x->new_ptr<If_t>(); |
9330 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); | 9944 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); |
9331 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); | 9945 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); |
9332 | ifNode->nodes.push_back(with->body); | 9946 | ifNode->nodes.push_back(with->body); |
9333 | transformIf(ifNode, temp, ExpUsage::Common); | 9947 | if (breakWithVar.empty()) { |
9948 | transformIf(ifNode, temp, ExpUsage::Common); | ||
9949 | } else { | ||
9950 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
9951 | simpleValue->value.set(ifNode); | ||
9952 | auto exp = newExp(simpleValue, x); | ||
9953 | auto expList = x->new_ptr<ExpList_t>(); | ||
9954 | expList->exprs.push_back(exp); | ||
9955 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
9956 | expListAssign->expList.set(expList); | ||
9957 | auto stmt = x->new_ptr<Statement_t>(); | ||
9958 | stmt->content.set(expListAssign); | ||
9959 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); | ||
9960 | auto block = x->new_ptr<Block_t>(); | ||
9961 | block->statements.push_back(stmt); | ||
9962 | repeatNode->body.set(block); | ||
9963 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
9964 | sVal->value.set(repeatNode); | ||
9965 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | ||
9966 | transformAssignment(asmt, temp); | ||
9967 | } | ||
9334 | } else { | 9968 | } else { |
9335 | bool transformed = false; | 9969 | bool transformed = false; |
9336 | if (!extraScope && assignList) { | 9970 | if (!breakWithVar.empty()) { |
9971 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); | ||
9972 | auto block = x->new_ptr<Block_t>(); | ||
9973 | if (auto blk = with->body.as<Block_t>()) { | ||
9974 | block->statements.dup(blk->statements); | ||
9975 | } else { | ||
9976 | auto stmt = with->body.to<Statement_t>(); | ||
9977 | block->statements.push_back(stmt); | ||
9978 | } | ||
9979 | repeatNode->body.set(block); | ||
9980 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
9981 | sVal->value.set(repeatNode); | ||
9982 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | ||
9983 | transformAssignment(asmt, temp); | ||
9984 | transformed = true; | ||
9985 | } else if (!extraScope && assignList) { | ||
9337 | if (auto block = with->body.as<Block_t>()) { | 9986 | if (auto block = with->body.as<Block_t>()) { |
9338 | if (!block->statements.empty()) { | 9987 | if (!block->statements.empty()) { |
9339 | Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); | 9988 | Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); |
@@ -9398,12 +10047,18 @@ private: | |||
9398 | switch (item->get_id()) { | 10047 | switch (item->get_id()) { |
9399 | case id<ClassDecl_t>(): { | 10048 | case id<ClassDecl_t>(): { |
9400 | auto classDecl = static_cast<ClassDecl_t*>(item); | 10049 | auto classDecl = static_cast<ClassDecl_t*>(item); |
10050 | std::string varName; | ||
9401 | if (classDecl->name) { | 10051 | if (classDecl->name) { |
9402 | if (auto var = classDecl->name->item.as<Variable_t>()) { | 10052 | if (auto var = classDecl->name->item.as<Variable_t>()) { |
9403 | addGlobalVar(variableToString(var), classDecl->name->item); | 10053 | varName = variableToString(var); |
10054 | addGlobalVar(varName, var); | ||
9404 | } | 10055 | } |
9405 | } | 10056 | } |
10057 | if (varName.empty()) { | ||
10058 | throw CompileError("missing name for class", classDecl); | ||
10059 | } | ||
9406 | transformClassDecl(classDecl, out, ExpUsage::Common); | 10060 | transformClassDecl(classDecl, out, ExpUsage::Common); |
10061 | markVarGlobalConst(varName); | ||
9407 | break; | 10062 | break; |
9408 | } | 10063 | } |
9409 | case id<GlobalOp_t>(): | 10064 | case id<GlobalOp_t>(): |
@@ -9417,9 +10072,11 @@ private: | |||
9417 | auto values = global->item.to<GlobalValues_t>(); | 10072 | auto values = global->item.to<GlobalValues_t>(); |
9418 | if (values->valueList) { | 10073 | if (values->valueList) { |
9419 | auto expList = x->new_ptr<ExpList_t>(); | 10074 | auto expList = x->new_ptr<ExpList_t>(); |
10075 | str_list varNames; | ||
9420 | for (auto name : values->nameList->names.objects()) { | 10076 | for (auto name : values->nameList->names.objects()) { |
9421 | auto var = static_cast<Variable_t*>(name); | 10077 | auto var = static_cast<Variable_t*>(name); |
9422 | addGlobalVar(variableToString(var), var); | 10078 | varNames.emplace_back(variableToString(var)); |
10079 | addGlobalVar(varNames.back(), var); | ||
9423 | auto callable = x->new_ptr<Callable_t>(); | 10080 | auto callable = x->new_ptr<Callable_t>(); |
9424 | callable->item.set(name); | 10081 | callable->item.set(name); |
9425 | auto chainValue = x->new_ptr<ChainValue_t>(); | 10082 | auto chainValue = x->new_ptr<ChainValue_t>(); |
@@ -9438,10 +10095,17 @@ private: | |||
9438 | } | 10095 | } |
9439 | assignment->action.set(assign); | 10096 | assignment->action.set(assign); |
9440 | transformAssignment(assignment, out); | 10097 | transformAssignment(assignment, out); |
10098 | for (const auto& name : varNames) { | ||
10099 | markVarGlobalConst(name); | ||
10100 | } | ||
9441 | } else { | 10101 | } else { |
9442 | for (auto name : values->nameList->names.objects()) { | 10102 | for (auto name : values->nameList->names.objects()) { |
9443 | auto var = static_cast<Variable_t*>(name); | 10103 | auto var = static_cast<Variable_t*>(name); |
9444 | addGlobalVar(variableToString(var), var); | 10104 | auto varName = variableToString(var); |
10105 | addGlobalVar(varName, var); | ||
10106 | if (global->constAttrib) { | ||
10107 | markVarGlobalConst(varName); | ||
10108 | } | ||
9445 | } | 10109 | } |
9446 | } | 10110 | } |
9447 | break; | 10111 | break; |
@@ -9790,8 +10454,47 @@ private: | |||
9790 | out.push_back(join(temp)); | 10454 | out.push_back(join(temp)); |
9791 | } | 10455 | } |
9792 | 10456 | ||
9793 | void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage) { | 10457 | void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
9794 | auto x = tryNode; | 10458 | auto x = tryNode; |
10459 | if (tryNode->eop && usage == ExpUsage::Assignment) { | ||
10460 | str_list rets; | ||
10461 | pushScope(); | ||
10462 | auto okVar = getUnusedName("_ok_"sv); | ||
10463 | for (size_t i = 0; i < assignList->exprs.size(); i++) { | ||
10464 | auto retVar = getUnusedName("_ret_"sv); | ||
10465 | rets.emplace_back(retVar); | ||
10466 | addToScope(retVar); | ||
10467 | } | ||
10468 | popScope(); | ||
10469 | auto varList = join(rets, ","sv); | ||
10470 | auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x); | ||
10471 | auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front(); | ||
10472 | auto sVal = simpleSingleValueFrom(exp); | ||
10473 | auto newTry = sVal->value.to<Try_t>(); | ||
10474 | newTry->func.set(tryNode->func); | ||
10475 | newTry->catchBlock.set(tryNode->catchBlock); | ||
10476 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
10477 | assignment->expList.set(assignList); | ||
10478 | auto assign = x->new_ptr<Assign_t>(); | ||
10479 | assign->values.push_back(ifNode); | ||
10480 | assignment->action.set(assign); | ||
10481 | transformAssignment(assignment, out); | ||
10482 | return; | ||
10483 | } | ||
10484 | if (tryNode->eop && usage != ExpUsage::Common) { | ||
10485 | auto okVar = getUnusedName("_ok_"sv); | ||
10486 | auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar; | ||
10487 | auto doNode = toAst<Do_t>(code, x); | ||
10488 | auto block = doNode->body->content.to<Block_t>(); | ||
10489 | auto asmt = static_cast<Statement_t*>(block->statements.front())->content.to<ExpListAssign_t>(); | ||
10490 | auto assign = asmt->action.to<Assign_t>(); | ||
10491 | auto sVal = simpleSingleValueFrom(assign->values.back()); | ||
10492 | auto newTry = sVal->value.to<Try_t>(); | ||
10493 | newTry->func.set(tryNode->func); | ||
10494 | newTry->catchBlock.set(tryNode->catchBlock); | ||
10495 | transformDo(doNode, out, usage); | ||
10496 | return; | ||
10497 | } | ||
9795 | ast_ptr<true, Exp_t> errHandler; | 10498 | ast_ptr<true, Exp_t> errHandler; |
9796 | if (tryNode->catchBlock) { | 10499 | if (tryNode->catchBlock) { |
9797 | auto catchBlock = tryNode->catchBlock.get(); | 10500 | auto catchBlock = tryNode->catchBlock.get(); |
@@ -10103,7 +10806,7 @@ private: | |||
10103 | out.push_back(join(temp)); | 10806 | out.push_back(join(temp)); |
10104 | auto vars = getAssignVars(assignment); | 10807 | auto vars = getAssignVars(assignment); |
10105 | for (const auto& var : vars) { | 10808 | for (const auto& var : vars) { |
10106 | markVarConst(var); | 10809 | markVarLocalConst(var); |
10107 | } | 10810 | } |
10108 | } | 10811 | } |
10109 | 10812 | ||
@@ -10331,12 +11034,36 @@ private: | |||
10331 | transformAssignment(assignment, out); | 11034 | transformAssignment(assignment, out); |
10332 | if (auto var = ast_cast<Variable_t>(target)) { | 11035 | if (auto var = ast_cast<Variable_t>(target)) { |
10333 | auto moduleName = variableToString(var); | 11036 | auto moduleName = variableToString(var); |
10334 | markVarConst(moduleName); | 11037 | markVarLocalConst(moduleName); |
10335 | } else { | 11038 | } else { |
10336 | markDestructureConst(assignment); | 11039 | markDestructureConst(assignment); |
10337 | } | 11040 | } |
10338 | } | 11041 | } |
10339 | 11042 | ||
11043 | void transformImportGlobal(ImportGlobal_t* importNode, str_list& out) { | ||
11044 | auto uname = static_cast<UnicodeName_t*>(importNode->segs.front()); | ||
11045 | auto var = _parser.toString(uname); | ||
11046 | auto isNormal = _parser.match<Name_t>(var) && _parser.match<Variable_t>(var); | ||
11047 | auto varName = unicodeVariableFrom(uname); | ||
11048 | str_list temp; | ||
11049 | auto it = ++importNode->segs.objects().begin(); | ||
11050 | for (; it != importNode->segs.objects().end(); ++it) { | ||
11051 | temp.emplace_back(_parser.toString(*it)); | ||
11052 | } | ||
11053 | temp.emplace_front(var); | ||
11054 | if (isLocal(varName) || !isNormal) { | ||
11055 | temp.emplace_front("_G"s); | ||
11056 | } | ||
11057 | std::string stmt; | ||
11058 | if (importNode->target) { | ||
11059 | stmt = "const "s + _parser.toString(importNode->target) + '=' + join(temp, "."sv); | ||
11060 | } else { | ||
11061 | stmt = "const "s + temp.back() + '=' + join(temp, "."sv); | ||
11062 | } | ||
11063 | auto localAttrib = toAst<LocalAttrib_t>(stmt, importNode); | ||
11064 | transformLocalAttrib(localAttrib, out); | ||
11065 | } | ||
11066 | |||
10340 | void transformImport(Import_t* import, str_list& out) { | 11067 | void transformImport(Import_t* import, str_list& out) { |
10341 | auto content = import->content.get(); | 11068 | auto content = import->content.get(); |
10342 | switch (content->get_id()) { | 11069 | switch (content->get_id()) { |
@@ -10349,6 +11076,9 @@ private: | |||
10349 | case id<FromImport_t>(): | 11076 | case id<FromImport_t>(): |
10350 | transformFromImport(static_cast<FromImport_t*>(content), out); | 11077 | transformFromImport(static_cast<FromImport_t*>(content), out); |
10351 | break; | 11078 | break; |
11079 | case id<ImportGlobal_t>(): | ||
11080 | transformImportGlobal(static_cast<ImportGlobal_t*>(content), out); | ||
11081 | break; | ||
10352 | default: YUEE("AST node mismatch", content); break; | 11082 | default: YUEE("AST node mismatch", content); break; |
10353 | } | 11083 | } |
10354 | } | 11084 | } |
@@ -10368,15 +11098,27 @@ private: | |||
10368 | addToScope(accumVar); | 11098 | addToScope(accumVar); |
10369 | auto lenVar = getUnusedName("_len_"sv); | 11099 | auto lenVar = getUnusedName("_len_"sv); |
10370 | addToScope(lenVar); | 11100 | addToScope(lenVar); |
10371 | temp.push_back(indent() + "local "s + accumVar + " = { }"s + nll(whileNode)); | 11101 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); |
10372 | temp.push_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | 11102 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(whileNode); |
11103 | temp.emplace_back(clearBuf()); | ||
11104 | _buf << indent() << "local "s << lenVar << " = 1"s << nll(whileNode); | ||
11105 | auto& lenAssign = temp.emplace_back(clearBuf()); | ||
10373 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11106 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
10374 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11107 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
10375 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 11108 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); |
10376 | pushScope(); | 11109 | pushScope(); |
10377 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 11110 | if (hasBreakWithValue(breakLoopType)) { |
10378 | auto lenLine = lenVar + " = "s + lenVar + " + 1"s + nlr(whileNode); | 11111 | lenAssign.clear(); |
10379 | transformLoopBody(whileNode->body, temp, lenLine, ExpUsage::Assignment, assignLeft); | 11112 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); |
11113 | } else { | ||
11114 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
11115 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
11116 | assignLeft->followStmt = followStmt.get(); | ||
11117 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
11118 | if (!assignLeft->followStmtProcessed) { | ||
11119 | lenAssign.clear(); | ||
11120 | } | ||
11121 | } | ||
10380 | popScope(); | 11122 | popScope(); |
10381 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11123 | temp.push_back(indent() + "end"s + nlr(whileNode)); |
10382 | if (expList) { | 11124 | if (expList) { |
@@ -10412,15 +11154,26 @@ private: | |||
10412 | addToScope(accumVar); | 11154 | addToScope(accumVar); |
10413 | auto lenVar = getUnusedName("_len_"sv); | 11155 | auto lenVar = getUnusedName("_len_"sv); |
10414 | addToScope(lenVar); | 11156 | addToScope(lenVar); |
10415 | temp.push_back(indent() + "local "s + accumVar + " = { }"s + nll(whileNode)); | 11157 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); |
10416 | temp.push_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | 11158 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(whileNode); |
11159 | temp.emplace_back(clearBuf()); | ||
11160 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | ||
10417 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11161 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
10418 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11162 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
10419 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 11163 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); |
10420 | pushScope(); | 11164 | pushScope(); |
10421 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 11165 | if (hasBreakWithValue(breakLoopType)) { |
10422 | auto lenLine = lenVar + " = "s + lenVar + " + 1"s + nlr(whileNode); | 11166 | lenAssign.clear(); |
10423 | transformLoopBody(whileNode->body, temp, lenLine, ExpUsage::Assignment, assignLeft); | 11167 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); |
11168 | } else { | ||
11169 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
11170 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
11171 | assignLeft->followStmt = followStmt.get(); | ||
11172 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
11173 | if (!assignLeft->followStmtProcessed) { | ||
11174 | lenAssign.clear(); | ||
11175 | } | ||
11176 | } | ||
10424 | popScope(); | 11177 | popScope(); |
10425 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11178 | temp.push_back(indent() + "end"s + nlr(whileNode)); |
10426 | temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); | 11179 | temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); |
@@ -10455,9 +11208,7 @@ private: | |||
10455 | expListAssign->expList.set(expList); | 11208 | expListAssign->expList.set(expList); |
10456 | auto stmt = x->new_ptr<Statement_t>(); | 11209 | auto stmt = x->new_ptr<Statement_t>(); |
10457 | stmt->content.set(expListAssign); | 11210 | stmt->content.set(expListAssign); |
10458 | auto body = x->new_ptr<Body_t>(); | 11211 | repeat->body.set(stmt); |
10459 | body->content.set(stmt); | ||
10460 | repeat->body.set(body); | ||
10461 | transformRepeat(repeat, out); | 11212 | transformRepeat(repeat, out); |
10462 | return; | 11213 | return; |
10463 | } | 11214 | } |
@@ -10465,7 +11216,8 @@ private: | |||
10465 | pushScope(); | 11216 | pushScope(); |
10466 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11217 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
10467 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11218 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
10468 | transformLoopBody(whileNode->body, temp, Empty, ExpUsage::Common); | 11219 | auto breakLoopType = getBreakLoopType(whileNode->body, Empty); |
11220 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); | ||
10469 | popScope(); | 11221 | popScope(); |
10470 | _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode); | 11222 | _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode); |
10471 | _buf << temp.back(); | 11223 | _buf << temp.back(); |
@@ -10473,6 +11225,106 @@ private: | |||
10473 | out.push_back(clearBuf()); | 11225 | out.push_back(clearBuf()); |
10474 | } | 11226 | } |
10475 | 11227 | ||
11228 | void transformRepeatInPlace(Repeat_t* repeatNode, str_list& out, ExpList_t* expList = nullptr) { | ||
11229 | auto x = repeatNode; | ||
11230 | str_list temp; | ||
11231 | bool extraScope = false; | ||
11232 | if (expList) { | ||
11233 | if (!currentScope().lastStatement) { | ||
11234 | extraScope = true; | ||
11235 | temp.push_back(indent() + "do"s + nll(repeatNode)); | ||
11236 | pushScope(); | ||
11237 | } | ||
11238 | } | ||
11239 | auto accumVar = getUnusedName("_accum_"sv); | ||
11240 | addToScope(accumVar); | ||
11241 | auto lenVar = getUnusedName("_len_"sv); | ||
11242 | addToScope(lenVar); | ||
11243 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
11244 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(repeatNode); | ||
11245 | temp.emplace_back(clearBuf()); | ||
11246 | _buf << indent() << "local "s << lenVar << " = 1"s << nll(repeatNode); | ||
11247 | auto& lenAssign = temp.emplace_back(clearBuf()); | ||
11248 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
11249 | temp.push_back(indent() + "repeat"s + nll(repeatNode)); | ||
11250 | pushScope(); | ||
11251 | if (hasBreakWithValue(breakLoopType)) { | ||
11252 | lenAssign.clear(); | ||
11253 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
11254 | } else { | ||
11255 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
11256 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
11257 | assignLeft->followStmt = followStmt.get(); | ||
11258 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
11259 | if (!assignLeft->followStmtProcessed) { | ||
11260 | lenAssign.clear(); | ||
11261 | } | ||
11262 | } | ||
11263 | popScope(); | ||
11264 | temp.push_back(indent() + "until "s + condStr + nlr(repeatNode)); | ||
11265 | if (expList) { | ||
11266 | auto assign = x->new_ptr<Assign_t>(); | ||
11267 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); | ||
11268 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
11269 | assignment->expList.set(expList); | ||
11270 | assignment->action.set(assign); | ||
11271 | transformAssignment(assignment, temp); | ||
11272 | if (extraScope) popScope(); | ||
11273 | } else { | ||
11274 | temp.push_back(indent() + "return "s + accumVar + nlr(repeatNode)); | ||
11275 | } | ||
11276 | if (expList && extraScope) { | ||
11277 | temp.push_back(indent() + "end"s + nlr(repeatNode)); | ||
11278 | } | ||
11279 | out.push_back(join(temp)); | ||
11280 | } | ||
11281 | |||
11282 | void transformRepeatClosure(Repeat_t* repeatNode, str_list& out) { | ||
11283 | auto x = repeatNode; | ||
11284 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
11285 | simpleValue->value.set(repeatNode); | ||
11286 | if (transformAsUpValueFunc(newExp(simpleValue, x), out)) { | ||
11287 | return; | ||
11288 | } | ||
11289 | str_list temp; | ||
11290 | pushAnonFunctionScope(); | ||
11291 | pushAnonVarArg(); | ||
11292 | std::string& funcStart = temp.emplace_back(); | ||
11293 | pushScope(); | ||
11294 | auto accumVar = getUnusedName("_accum_"sv); | ||
11295 | addToScope(accumVar); | ||
11296 | auto lenVar = getUnusedName("_len_"sv); | ||
11297 | addToScope(lenVar); | ||
11298 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
11299 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(repeatNode); | ||
11300 | temp.emplace_back(clearBuf()); | ||
11301 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nll(repeatNode)); | ||
11302 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
11303 | temp.push_back(indent() + "repeat"s + nll(repeatNode)); | ||
11304 | pushScope(); | ||
11305 | if (hasBreakWithValue(breakLoopType)) { | ||
11306 | lenAssign.clear(); | ||
11307 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
11308 | } else { | ||
11309 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
11310 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
11311 | assignLeft->followStmt = followStmt.get(); | ||
11312 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
11313 | if (!assignLeft->followStmtProcessed) { | ||
11314 | lenAssign.clear(); | ||
11315 | } | ||
11316 | } | ||
11317 | popScope(); | ||
11318 | temp.push_back(indent() + "until "s + condStr + nlr(repeatNode)); | ||
11319 | temp.push_back(indent() + "return "s + accumVar + nlr(repeatNode)); | ||
11320 | popScope(); | ||
11321 | funcStart = anonFuncStart() + nll(repeatNode); | ||
11322 | temp.push_back(indent() + anonFuncEnd()); | ||
11323 | popAnonVarArg(); | ||
11324 | popFunctionScope(); | ||
11325 | out.push_back(join(temp)); | ||
11326 | } | ||
11327 | |||
10476 | void transformRepeat(Repeat_t* repeat, str_list& out) { | 11328 | void transformRepeat(Repeat_t* repeat, str_list& out) { |
10477 | str_list temp; | 11329 | str_list temp; |
10478 | pushScope(); | 11330 | pushScope(); |
@@ -10506,10 +11358,26 @@ private: | |||
10506 | pushScope(); | 11358 | pushScope(); |
10507 | } | 11359 | } |
10508 | bool extraScope = false; | 11360 | bool extraScope = false; |
11361 | if (switchNode->assignment) { | ||
11362 | if (needScope) { | ||
11363 | extraScope = true; | ||
11364 | temp.push_back(indent() + "do"s + nll(x)); | ||
11365 | pushScope(); | ||
11366 | } | ||
11367 | auto asmt = x->new_ptr<ExpListAssign_t>(); | ||
11368 | auto expList = x->new_ptr<ExpList_t>(); | ||
11369 | expList->exprs.push_back(switchNode->target); | ||
11370 | if (switchNode->assignment->expList) { | ||
11371 | expList->exprs.dup(switchNode->assignment->expList->exprs); | ||
11372 | } | ||
11373 | asmt->expList.set(expList); | ||
11374 | asmt->action.set(switchNode->assignment->assign); | ||
11375 | transformAssignment(asmt, temp); | ||
11376 | } | ||
10509 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); | 11377 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); |
10510 | if (objVar.empty() || !isLocal(objVar)) { | 11378 | if (objVar.empty() || !isLocal(objVar)) { |
10511 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { | 11379 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { |
10512 | if (needScope) { | 11380 | if (needScope && !extraScope) { |
10513 | extraScope = true; | 11381 | extraScope = true; |
10514 | temp.push_back(indent() + "do"s + nll(x)); | 11382 | temp.push_back(indent() + "do"s + nll(x)); |
10515 | pushScope(); | 11383 | pushScope(); |
@@ -10567,8 +11435,9 @@ private: | |||
10567 | } | 11435 | } |
10568 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); | 11436 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); |
10569 | pushScope(); | 11437 | pushScope(); |
10570 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), toAst<Exp_t>(objVar, branch), branch); | 11438 | auto chainValue = toAst<ChainValue_t>(objVar, branch); |
10571 | auto info = extractDestructureInfo(assignment, true, false); | 11439 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), newExp(chainValue, branch), branch); |
11440 | auto info = extractDestructureInfo(assignment, true, true); | ||
10572 | transformAssignment(assignment, temp, true); | 11441 | transformAssignment(assignment, temp, true); |
10573 | str_list conds; | 11442 | str_list conds; |
10574 | for (const auto& des : info.destructures) { | 11443 | for (const auto& des : info.destructures) { |
@@ -10578,8 +11447,31 @@ private: | |||
10578 | const auto& destruct = std::get<Destructure>(des); | 11447 | const auto& destruct = std::get<Destructure>(des); |
10579 | for (const auto& item : destruct.items) { | 11448 | for (const auto& item : destruct.items) { |
10580 | if (!item.defVal) { | 11449 | if (!item.defVal) { |
10581 | transformExp(item.target, conds, ExpUsage::Closure); | 11450 | if (!isAssignable(item.target)) { |
10582 | conds.back().append(" ~= nil"s); | 11451 | auto callable = chainValue->items.front(); |
11452 | auto chain = callable->new_ptr<ChainValue_t>(); | ||
11453 | chain->items.push_back(callable); | ||
11454 | chain->items.dup(item.structure->items); | ||
11455 | if (specialChainValue(chain) == ChainType::Common) { | ||
11456 | transformChainValue(chain, conds, ExpUsage::Closure); | ||
11457 | auto vStr = conds.back(); | ||
11458 | conds.pop_back(); | ||
11459 | transformExp(item.target, conds, ExpUsage::Closure); | ||
11460 | conds.back().append(" == "s); | ||
11461 | conds.back().append(vStr); | ||
11462 | } else { | ||
11463 | auto varName = getUnusedName("_val_"sv); | ||
11464 | auto vExp = toAst<Exp_t>(varName, chain); | ||
11465 | auto asmt = assignmentFrom(vExp, newExp(chain, chain), chain); | ||
11466 | transformAssignment(asmt, temp); | ||
11467 | transformExp(item.target, conds, ExpUsage::Closure); | ||
11468 | conds.back().append(" == "s); | ||
11469 | conds.back().append(varName); | ||
11470 | } | ||
11471 | } else { | ||
11472 | transformExp(item.target, conds, ExpUsage::Closure); | ||
11473 | conds.back().append(" ~= nil"s); | ||
11474 | } | ||
10583 | } | 11475 | } |
10584 | } | 11476 | } |
10585 | } | 11477 | } |
@@ -10877,7 +11769,7 @@ private: | |||
10877 | } | 11769 | } |
10878 | transformAssignment(assignment, temp); | 11770 | transformAssignment(assignment, temp); |
10879 | for (const auto& name : vars) { | 11771 | for (const auto& name : vars) { |
10880 | markVarConst(name); | 11772 | markVarLocalConst(name); |
10881 | } | 11773 | } |
10882 | if (localAttrib->attrib.is<CloseAttrib_t>()) { | 11774 | if (localAttrib->attrib.is<CloseAttrib_t>()) { |
10883 | str_list leftVars, rightVars; | 11775 | str_list leftVars, rightVars; |
@@ -10949,7 +11841,7 @@ private: | |||
10949 | temp.push_back(indent() + "local "s + join(leftVars, ", "sv) + " = "s + join(items, ", "sv) + nll(x)); | 11841 | temp.push_back(indent() + "local "s + join(leftVars, ", "sv) + " = "s + join(items, ", "sv) + nll(x)); |
10950 | } | 11842 | } |
10951 | for (const auto& var : vars) { | 11843 | for (const auto& var : vars) { |
10952 | markVarConst(var); | 11844 | markVarLocalConst(var); |
10953 | } | 11845 | } |
10954 | } | 11846 | } |
10955 | if (!listB->exprs.empty()) { | 11847 | if (!listB->exprs.empty()) { |
@@ -10974,18 +11866,24 @@ private: | |||
10974 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); | 11866 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); |
10975 | transformAssignment(assignment, temp); | 11867 | transformAssignment(assignment, temp); |
10976 | for (const auto& name : vars) { | 11868 | for (const auto& name : vars) { |
10977 | markVarConst(name); | 11869 | markVarLocalConst(name); |
10978 | } | 11870 | } |
10979 | } | 11871 | } |
10980 | out.push_back(join(temp)); | 11872 | out.push_back(join(temp)); |
10981 | } | 11873 | } |
10982 | 11874 | ||
10983 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { | 11875 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { |
10984 | auto keyword = _parser.toString(breakLoop); | 11876 | auto isBreak = breakLoop->type.is<Break_t>(); |
11877 | auto keyword = isBreak ? "break"s : "continue"s; | ||
10985 | if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { | 11878 | if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { |
10986 | throw CompileError(keyword + " is not inside a loop"s, breakLoop); | 11879 | throw CompileError(keyword + " is not inside a loop"s, breakLoop); |
10987 | } | 11880 | } |
10988 | if (keyword == "break"sv) { | 11881 | if (isBreak) { |
11882 | if (breakLoop->value) { | ||
11883 | auto exp = toAst<Exp_t>(breakLoop->varBWV, breakLoop->value); | ||
11884 | auto assignment = assignmentFrom(exp, breakLoop->value, breakLoop); | ||
11885 | transformAssignment(assignment, out); | ||
11886 | } | ||
10989 | out.push_back(indent() + keyword + nll(breakLoop)); | 11887 | out.push_back(indent() + keyword + nll(breakLoop)); |
10990 | return; | 11888 | return; |
10991 | } | 11889 | } |
diff --git a/src/yuescript/yue_compiler.h b/src/yuescript/yue_compiler.h index d352636..aff5978 100644 --- a/src/yuescript/yue_compiler.h +++ b/src/yuescript/yue_compiler.h | |||
@@ -31,6 +31,7 @@ struct YueConfig { | |||
31 | bool reserveLineNumber = true; | 31 | bool reserveLineNumber = true; |
32 | bool useSpaceOverTab = false; | 32 | bool useSpaceOverTab = false; |
33 | bool reserveComment = false; | 33 | bool reserveComment = false; |
34 | bool lax = false; | ||
34 | // internal options | 35 | // internal options |
35 | bool exporting = false; | 36 | bool exporting = false; |
36 | bool profiling = false; | 37 | bool profiling = false; |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index ceb1f7c..1942e23 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -67,24 +67,28 @@ YueParser::YueParser() { | |||
67 | num_char = range('0', '9') >> *(range('0', '9') | '_' >> and_(range('0', '9'))); | 67 | num_char = range('0', '9') >> *(range('0', '9') | '_' >> and_(range('0', '9'))); |
68 | num_char_hex = range('0', '9') | range('a', 'f') | range('A', 'F'); | 68 | num_char_hex = range('0', '9') | range('a', 'f') | range('A', 'F'); |
69 | num_lit = num_char_hex >> *(num_char_hex | '_' >> and_(num_char_hex)); | 69 | num_lit = num_char_hex >> *(num_char_hex | '_' >> and_(num_char_hex)); |
70 | num_bin_lit = set("01") >> *(set("01") | '_' >> and_(set("01"))); | ||
70 | Num = | 71 | Num = |
71 | "0x" >> ( | 72 | '0' >> ( |
72 | +num_lit >> ( | 73 | set("xX") >> ( |
73 | '.' >> +num_lit >> -num_expo_hex | | 74 | num_lit >> ( |
74 | num_expo_hex | | 75 | '.' >> num_lit >> -num_expo_hex | |
75 | lj_num | | 76 | num_expo_hex | |
76 | true_() | 77 | lj_num | |
77 | ) | ( | 78 | true_() |
78 | '.' >> +num_lit >> -num_expo_hex | 79 | ) | ( |
79 | ) | 80 | '.' >> num_lit >> -num_expo_hex |
81 | ) | ||
82 | ) | | ||
83 | set("bB") >> num_bin_lit | ||
80 | ) | | 84 | ) | |
81 | +num_char >> ( | 85 | num_char >> ( |
82 | '.' >> +num_char >> -num_expo | | 86 | '.' >> num_char >> -num_expo | |
83 | num_expo | | 87 | num_expo | |
84 | lj_num | | 88 | lj_num | |
85 | true_() | 89 | true_() |
86 | ) | | 90 | ) | |
87 | '.' >> +num_char >> -num_expo; | 91 | '.' >> num_char >> -num_expo; |
88 | 92 | ||
89 | cut = false_(); | 93 | cut = false_(); |
90 | Seperator = true_(); | 94 | Seperator = true_(); |
@@ -114,8 +118,8 @@ YueParser::YueParser() { | |||
114 | return false; | 118 | return false; |
115 | }); | 119 | }); |
116 | 120 | ||
117 | if_assignment_syntax_error = pl::user(true_(), [](const item_t& item) { | 121 | assignment_expression_syntax_error = pl::user(true_(), [](const item_t& item) { |
118 | throw ParserError("use := for if-assignment expression"sv, item.begin); | 122 | throw ParserError("use := for assignment expression"sv, item.begin); |
119 | return false; | 123 | return false; |
120 | }); | 124 | }); |
121 | 125 | ||
@@ -158,6 +162,13 @@ YueParser::YueParser() { | |||
158 | ) \ | 162 | ) \ |
159 | ) | 163 | ) |
160 | 164 | ||
165 | #define disable_until_rule(patt) ( \ | ||
166 | disable_until >> ( \ | ||
167 | (patt) >> enable_until | \ | ||
168 | enable_until >> cut \ | ||
169 | ) \ | ||
170 | ) | ||
171 | |||
161 | #define body_with(str) ( \ | 172 | #define body_with(str) ( \ |
162 | key(str) >> space >> (in_block | Statement) | \ | 173 | key(str) >> space >> (in_block | Statement) | \ |
163 | in_block | \ | 174 | in_block | \ |
@@ -321,7 +332,7 @@ YueParser::YueParser() { | |||
321 | Exp; | 332 | Exp; |
322 | import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); | 333 | import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); |
323 | import_tab_line = ( | 334 | import_tab_line = ( |
324 | push_indent_match >> (space >> import_tab_list >> pop_indent | pop_indent) | 335 | push_indent_match >> ensure(space >> import_tab_list, pop_indent) |
325 | ) | space; | 336 | ) | space; |
326 | import_tab_lines = space_break >> import_tab_line >> *(-(space >> ',') >> space_break >> import_tab_line) >> -(space >> ','); | 337 | import_tab_lines = space_break >> import_tab_line >> *(-(space >> ',') >> space_break >> import_tab_line) >> -(space >> ','); |
327 | import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; | 338 | import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; |
@@ -338,7 +349,9 @@ YueParser::YueParser() { | |||
338 | 349 | ||
339 | ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro)); | 350 | ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro)); |
340 | 351 | ||
341 | Import = key("import") >> space >> (ImportAs | ImportFrom) | FromImport; | 352 | ImportGlobal = Seperator >> UnicodeName >> *('.' >> UnicodeName) >> -(space >> key("as") >> space >> Variable); |
353 | |||
354 | Import = key("import") >> space >> (ImportAs | ImportFrom | ImportGlobal) | FromImport; | ||
342 | 355 | ||
343 | Label = "::" >> LabelName >> "::"; | 356 | Label = "::" >> LabelName >> "::"; |
344 | 357 | ||
@@ -346,11 +359,13 @@ YueParser::YueParser() { | |||
346 | 359 | ||
347 | ShortTabAppending = "[]" >> space >> Assign; | 360 | ShortTabAppending = "[]" >> space >> Assign; |
348 | 361 | ||
349 | BreakLoop = (expr("break") | "continue") >> not_alpha_num; | 362 | Break = key("break"); |
363 | Continue = key("continue"); | ||
364 | BreakLoop = (Break >> -(space >> Exp) | Continue) >> not_alpha_num; | ||
350 | 365 | ||
351 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); | 366 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); |
352 | 367 | ||
353 | with_exp = ExpList >> -(space >> Assign); | 368 | with_exp = ExpList >> -(space >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error)); |
354 | 369 | ||
355 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); | 370 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); |
356 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); | 371 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); |
@@ -366,7 +381,8 @@ YueParser::YueParser() { | |||
366 | and_(SimpleTable | TableLit) >> Exp | | 381 | and_(SimpleTable | TableLit) >> Exp | |
367 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) | 382 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) |
368 | ); | 383 | ); |
369 | Switch = key("switch") >> space >> Exp >> | 384 | Switch = key("switch") >> space >> |
385 | Exp >> -(space >> Assignment) >> | ||
370 | space >> Seperator >> ( | 386 | space >> Seperator >> ( |
371 | SwitchCase >> space >> ( | 387 | SwitchCase >> space >> ( |
372 | switch_block | | 388 | switch_block | |
@@ -375,20 +391,26 @@ YueParser::YueParser() { | |||
375 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent | 391 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent |
376 | ); | 392 | ); |
377 | 393 | ||
378 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error); | 394 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error); |
379 | IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))); | 395 | IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))); |
380 | if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); | 396 | if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); |
381 | if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; | 397 | if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; |
382 | IfType = (expr("if") | "unless") >> not_alpha_num; | 398 | IfType = (expr("if") | "unless") >> not_alpha_num; |
383 | If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; | 399 | If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; |
384 | 400 | ||
385 | WhileType = (expr("while") | "until") >> not_alpha_num; | 401 | WhileType = (expr("while") | pl::user("until", [](const item_t& item) { |
386 | While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do"); | 402 | State* st = reinterpret_cast<State*>(item.user_data); |
387 | Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; | 403 | return st->noUntilStack.empty() || !st->noUntilStack.back(); |
404 | })) >> not_alpha_num; | ||
405 | While = key(WhileType) >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do"); | ||
406 | Repeat = key("repeat") >> space >> ( | ||
407 | in_block >> line_break >> *space_break >> check_indent_match | | ||
408 | disable_until_rule(Statement) | ||
409 | ) >> space >> key("until") >> space >> Exp; | ||
388 | 410 | ||
389 | for_key = pl::user(key("for"), [](const item_t& item) { | 411 | for_key = pl::user(key("for"), [](const item_t& item) { |
390 | State* st = reinterpret_cast<State*>(item.user_data); | 412 | State* st = reinterpret_cast<State*>(item.user_data); |
391 | return st->noForStack.empty() || !st->noForStack.top(); | 413 | return st->noForStack.empty() || !st->noForStack.back(); |
392 | }); | 414 | }); |
393 | ForStepValue = ',' >> space >> Exp; | 415 | ForStepValue = ',' >> space >> Exp; |
394 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; | 416 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; |
@@ -402,18 +424,18 @@ YueParser::YueParser() { | |||
402 | 424 | ||
403 | Do = pl::user(key("do"), [](const item_t& item) { | 425 | Do = pl::user(key("do"), [](const item_t& item) { |
404 | State* st = reinterpret_cast<State*>(item.user_data); | 426 | State* st = reinterpret_cast<State*>(item.user_data); |
405 | return st->noDoStack.empty() || !st->noDoStack.top(); | 427 | return st->noDoStack.empty() || !st->noDoStack.back(); |
406 | }) >> space >> Body; | 428 | }) >> space >> Body; |
407 | 429 | ||
408 | disable_do = pl::user(true_(), [](const item_t& item) { | 430 | disable_do = pl::user(true_(), [](const item_t& item) { |
409 | State* st = reinterpret_cast<State*>(item.user_data); | 431 | State* st = reinterpret_cast<State*>(item.user_data); |
410 | st->noDoStack.push(true); | 432 | st->noDoStack.push_back(true); |
411 | return true; | 433 | return true; |
412 | }); | 434 | }); |
413 | 435 | ||
414 | enable_do = pl::user(true_(), [](const item_t& item) { | 436 | enable_do = pl::user(true_(), [](const item_t& item) { |
415 | State* st = reinterpret_cast<State*>(item.user_data); | 437 | State* st = reinterpret_cast<State*>(item.user_data); |
416 | st->noDoStack.pop(); | 438 | st->noDoStack.pop_back(); |
417 | return true; | 439 | return true; |
418 | }); | 440 | }); |
419 | 441 | ||
@@ -431,46 +453,58 @@ YueParser::YueParser() { | |||
431 | 453 | ||
432 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 454 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
433 | State* st = reinterpret_cast<State*>(item.user_data); | 455 | State* st = reinterpret_cast<State*>(item.user_data); |
434 | st->noDoStack.push(true); | 456 | st->noDoStack.push_back(true); |
435 | st->noChainBlockStack.push(true); | 457 | st->noChainBlockStack.push_back(true); |
436 | st->noTableBlockStack.push(true); | 458 | st->noTableBlockStack.push_back(true); |
437 | return true; | 459 | return true; |
438 | }); | 460 | }); |
439 | 461 | ||
440 | enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 462 | enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
441 | State* st = reinterpret_cast<State*>(item.user_data); | 463 | State* st = reinterpret_cast<State*>(item.user_data); |
442 | st->noDoStack.pop(); | 464 | st->noDoStack.pop_back(); |
443 | st->noChainBlockStack.pop(); | 465 | st->noChainBlockStack.pop_back(); |
444 | st->noTableBlockStack.pop(); | 466 | st->noTableBlockStack.pop_back(); |
445 | return true; | 467 | return true; |
446 | }); | 468 | }); |
447 | 469 | ||
448 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 470 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
449 | State* st = reinterpret_cast<State*>(item.user_data); | 471 | State* st = reinterpret_cast<State*>(item.user_data); |
450 | st->noTableBlockStack.push(true); | 472 | st->noTableBlockStack.push_back(true); |
451 | return true; | 473 | return true; |
452 | }); | 474 | }); |
453 | 475 | ||
454 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 476 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
455 | State* st = reinterpret_cast<State*>(item.user_data); | 477 | State* st = reinterpret_cast<State*>(item.user_data); |
456 | st->noTableBlockStack.pop(); | 478 | st->noTableBlockStack.pop_back(); |
457 | return true; | 479 | return true; |
458 | }); | 480 | }); |
459 | 481 | ||
460 | disable_for = pl::user(true_(), [](const item_t& item) { | 482 | disable_for = pl::user(true_(), [](const item_t& item) { |
461 | State* st = reinterpret_cast<State*>(item.user_data); | 483 | State* st = reinterpret_cast<State*>(item.user_data); |
462 | st->noForStack.push(true); | 484 | st->noForStack.push_back(true); |
463 | return true; | 485 | return true; |
464 | }); | 486 | }); |
465 | 487 | ||
466 | enable_for = pl::user(true_(), [](const item_t& item) { | 488 | enable_for = pl::user(true_(), [](const item_t& item) { |
467 | State* st = reinterpret_cast<State*>(item.user_data); | 489 | State* st = reinterpret_cast<State*>(item.user_data); |
468 | st->noForStack.pop(); | 490 | st->noForStack.pop_back(); |
491 | return true; | ||
492 | }); | ||
493 | |||
494 | disable_until = pl::user(true_(), [](const item_t& item) { | ||
495 | State* st = reinterpret_cast<State*>(item.user_data); | ||
496 | st->noUntilStack.push_back(true); | ||
497 | return true; | ||
498 | }); | ||
499 | |||
500 | enable_until = pl::user(true_(), [](const item_t& item) { | ||
501 | State* st = reinterpret_cast<State*>(item.user_data); | ||
502 | st->noUntilStack.pop_back(); | ||
469 | return true; | 503 | return true; |
470 | }); | 504 | }); |
471 | 505 | ||
472 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; | 506 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; |
473 | Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; | 507 | Try = key("try") >> -ExistentialOp >> space >> (in_block | Exp) >> -CatchBlock; |
474 | 508 | ||
475 | list_value = | 509 | list_value = |
476 | and_( | 510 | and_( |
@@ -557,20 +591,20 @@ YueParser::YueParser() { | |||
557 | 591 | ||
558 | disable_chain = pl::user(true_(), [](const item_t& item) { | 592 | disable_chain = pl::user(true_(), [](const item_t& item) { |
559 | State* st = reinterpret_cast<State*>(item.user_data); | 593 | State* st = reinterpret_cast<State*>(item.user_data); |
560 | st->noChainBlockStack.push(true); | 594 | st->noChainBlockStack.push_back(true); |
561 | return true; | 595 | return true; |
562 | }); | 596 | }); |
563 | 597 | ||
564 | enable_chain = pl::user(true_(), [](const item_t& item) { | 598 | enable_chain = pl::user(true_(), [](const item_t& item) { |
565 | State* st = reinterpret_cast<State*>(item.user_data); | 599 | State* st = reinterpret_cast<State*>(item.user_data); |
566 | st->noChainBlockStack.pop(); | 600 | st->noChainBlockStack.pop_back(); |
567 | return true; | 601 | return true; |
568 | }); | 602 | }); |
569 | 603 | ||
570 | chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; | 604 | chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; |
571 | chain_block = pl::user(true_(), [](const item_t& item) { | 605 | chain_block = pl::user(true_(), [](const item_t& item) { |
572 | State* st = reinterpret_cast<State*>(item.user_data); | 606 | State* st = reinterpret_cast<State*>(item.user_data); |
573 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); | 607 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.back(); |
574 | }) >> +space_break >> advance_match >> ensure( | 608 | }) >> +space_break >> advance_match >> ensure( |
575 | chain_line >> *(+space_break >> chain_line), pop_indent); | 609 | chain_line >> *(+space_break >> chain_line), pop_indent); |
576 | ChainValue = | 610 | ChainValue = |
@@ -607,7 +641,15 @@ YueParser::YueParser() { | |||
607 | DoubleStringInner = +(not_("#{") >> double_string_plain); | 641 | DoubleStringInner = +(not_("#{") >> double_string_plain); |
608 | DoubleStringContent = DoubleStringInner | interp; | 642 | DoubleStringContent = DoubleStringInner | interp; |
609 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; | 643 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; |
610 | String = DoubleString | SingleString | LuaString; | 644 | |
645 | YAMLIndent = +set(" \t"); | ||
646 | YAMLLineInner = +('\\' >> set("\"\\#") | not_("#{" | stop) >> any_char); | ||
647 | YAMLLineContent = YAMLLineInner | interp; | ||
648 | YAMLLine = check_indent_match >> YAMLIndent >> +(YAMLLineContent) | | ||
649 | advance_match >> YAMLIndent >> ensure(+YAMLLineContent, pop_indent); | ||
650 | YAMLMultiline = '|' >> space >> Seperator >> +(*set(" \t") >> line_break) >> advance_match >> ensure(YAMLLine >> *(+(*set(" \t") >> line_break) >> YAMLLine), pop_indent); | ||
651 | |||
652 | String = DoubleString | SingleString | LuaString | YAMLMultiline; | ||
611 | 653 | ||
612 | lua_string_open = '[' >> *expr('=') >> '['; | 654 | lua_string_open = '[' >> *expr('=') >> '['; |
613 | lua_string_close = ']' >> *expr('=') >> ']'; | 655 | lua_string_close = ']' >> *expr('=') >> ']'; |
@@ -635,7 +677,7 @@ YueParser::YueParser() { | |||
635 | fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); | 677 | fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); |
636 | 678 | ||
637 | fn_args_lit_line = ( | 679 | fn_args_lit_line = ( |
638 | push_indent_match >> (space >> fn_args_value_list >> pop_indent | pop_indent) | 680 | push_indent_match >> ensure(space >> fn_args_value_list, pop_indent) |
639 | ) | ( | 681 | ) | ( |
640 | space | 682 | space |
641 | ); | 683 | ); |
@@ -677,7 +719,8 @@ YueParser::YueParser() { | |||
677 | chain_with_colon = +chain_item >> -colon_chain; | 719 | chain_with_colon = +chain_item >> -colon_chain; |
678 | chain_items = chain_with_colon | colon_chain; | 720 | chain_items = chain_with_colon | colon_chain; |
679 | 721 | ||
680 | index = '[' >> not_('[') >> space >> Exp >> space >> ']'; | 722 | index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']'; |
723 | ReversedIndex = '#' >> space >> -('-' >> space >> Exp); | ||
681 | chain_item = | 724 | chain_item = |
682 | Invoke >> -ExistentialOp | | 725 | Invoke >> -ExistentialOp | |
683 | DotChainItem >> -ExistentialOp | | 726 | DotChainItem >> -ExistentialOp | |
@@ -734,7 +777,7 @@ YueParser::YueParser() { | |||
734 | 777 | ||
735 | table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line); | 778 | table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line); |
736 | TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); | 779 | TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); |
737 | TableBlockIndent = '*' >> Seperator >> disable_arg_table_block_rule( | 780 | TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule( |
738 | space >> key_value_list >> -(space >> ',') >> | 781 | space >> key_value_list >> -(space >> ',') >> |
739 | -(+space_break >> advance_match >> space >> ensure(key_value_list >> -(space >> ',') >> *(+space_break >> key_value_line), pop_indent))); | 782 | -(+space_break >> advance_match >> space >> ensure(key_value_list >> -(space >> ',') >> *(+space_break >> key_value_line), pop_indent))); |
740 | 783 | ||
@@ -755,7 +798,7 @@ YueParser::YueParser() { | |||
755 | 798 | ||
756 | GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); | 799 | GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); |
757 | GlobalOp = expr('*') | '^'; | 800 | GlobalOp = expr('*') | '^'; |
758 | Global = key("global") >> space >> (ClassDecl | GlobalOp | GlobalValues); | 801 | Global = key("global") >> space >> (-(ConstAttrib >> space) >> ClassDecl | GlobalOp | -(ConstAttrib >> space) >> GlobalValues); |
759 | 802 | ||
760 | ExportDefault = key("default"); | 803 | ExportDefault = key("default"); |
761 | 804 | ||
@@ -837,24 +880,24 @@ YueParser::YueParser() { | |||
837 | key_value_line = check_indent_match >> space >> ( | 880 | key_value_line = check_indent_match >> space >> ( |
838 | key_value_list >> -(space >> ',') | | 881 | key_value_list >> -(space >> ',') | |
839 | TableBlockIndent | | 882 | TableBlockIndent | |
840 | '*' >> space >> (SpreadExp | Exp | TableBlock) | 883 | ('*' | '-' >> space_one) >> space >> (SpreadExp | Exp | TableBlock) |
841 | ); | 884 | ); |
842 | 885 | ||
843 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); | 886 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); |
844 | 887 | ||
845 | fn_arg_def_lit_line = ( | 888 | fn_arg_def_lit_line = ( |
846 | push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent) | 889 | push_indent_match >> ensure(space >> fn_arg_def_list, pop_indent) |
847 | ) | ( | 890 | ) | ( |
848 | space | 891 | space |
849 | ); | 892 | ); |
850 | 893 | ||
851 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); | 894 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); |
852 | 895 | ||
853 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); | 896 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp); |
854 | 897 | ||
855 | FnArgDefList = Seperator >> ( | 898 | FnArgDefList = Seperator >> ( |
856 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) | | 899 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg >> -(space >> '`' >> space >> Name)) | |
857 | white >> VarArg | 900 | white >> VarArg >> -(space >> '`' >> space >> Name) |
858 | ); | 901 | ); |
859 | 902 | ||
860 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); | 903 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); |
@@ -883,6 +926,7 @@ YueParser::YueParser() { | |||
883 | 926 | ||
884 | FnArrowBack = '<' >> set("-="); | 927 | FnArrowBack = '<' >> set("-="); |
885 | Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; | 928 | Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; |
929 | SubBackcall = FnArrowBack >> space >> ChainValue; | ||
886 | 930 | ||
887 | PipeBody = Seperator >> | 931 | PipeBody = Seperator >> |
888 | pipe_operator >> space >> UnaryExp >> | 932 | pipe_operator >> space >> UnaryExp >> |
@@ -896,7 +940,7 @@ YueParser::YueParser() { | |||
896 | 940 | ||
897 | arg_table_block = pl::user(true_(), [](const item_t& item) { | 941 | arg_table_block = pl::user(true_(), [](const item_t& item) { |
898 | State* st = reinterpret_cast<State*>(item.user_data); | 942 | State* st = reinterpret_cast<State*>(item.user_data); |
899 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.top(); | 943 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.back(); |
900 | }) >> TableBlock; | 944 | }) >> TableBlock; |
901 | 945 | ||
902 | invoke_args_with_table = | 946 | invoke_args_with_table = |
@@ -936,11 +980,11 @@ YueParser::YueParser() { | |||
936 | 980 | ||
937 | SimpleValue = | 981 | SimpleValue = |
938 | TableLit | ConstValue | If | Switch | Try | With | | 982 | TableLit | ConstValue | If | Switch | Try | With | |
939 | ClassDecl | ForEach | For | While | Do | | 983 | ClassDecl | ForEach | For | While | Repeat | Do | |
940 | UnaryValue | TblComprehension | Comprehension | | 984 | UnaryValue | TblComprehension | Comprehension | |
941 | FunLit | Num | VarArg; | 985 | FunLit | Num | VarArg; |
942 | 986 | ||
943 | ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '='); | 987 | ExpListAssign = ExpList >> -(space >> (Update | Assign | SubBackcall)) >> not_(space >> '='); |
944 | 988 | ||
945 | IfLine = IfType >> space >> IfCond; | 989 | IfLine = IfType >> space >> IfCond; |
946 | WhileLine = WhileType >> space >> Exp; | 990 | WhileLine = WhileType >> space >> Exp; |
@@ -997,11 +1041,16 @@ YueParser::YueParser() { | |||
997 | empty_line_break | | 1041 | empty_line_break | |
998 | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) | 1042 | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) |
999 | ); | 1043 | ); |
1000 | Block = Seperator >> line >> *(+line_break >> line); | 1044 | Block = Seperator >> (pl::user(true_(), [](const item_t& item) { |
1045 | State* st = reinterpret_cast<State*>(item.user_data); | ||
1046 | return st->lax; | ||
1047 | }) >> lax_line >> *(+line_break >> lax_line) | line >> *(+line_break >> line)); | ||
1001 | 1048 | ||
1002 | shebang = "#!" >> *(not_(stop) >> any_char); | 1049 | shebang = "#!" >> *(not_(stop) >> any_char); |
1003 | BlockEnd = Block >> white >> stop; | 1050 | BlockEnd = Block >> white >> stop; |
1004 | File = -shebang >> -Block >> white >> stop; | 1051 | File = -shebang >> -Block >> white >> stop; |
1052 | |||
1053 | lax_line = advance_match >> ensure(*(not_(stop) >> any()), pop_indent) | line >> and_(stop) | check_indent_match >> *(not_(stop) >> any()); | ||
1005 | } | 1054 | } |
1006 | // clang-format on | 1055 | // clang-format on |
1007 | 1056 | ||
@@ -1031,7 +1080,7 @@ bool YueParser::startWith(std::string_view codes, rule& r) { | |||
1031 | return true; | 1080 | return true; |
1032 | } | 1081 | } |
1033 | 1082 | ||
1034 | ParseInfo YueParser::parse(std::string_view codes, rule& r) { | 1083 | ParseInfo YueParser::parse(std::string_view codes, rule& r, bool lax) { |
1035 | ParseInfo res; | 1084 | ParseInfo res; |
1036 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { | 1085 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { |
1037 | codes = codes.substr(3); | 1086 | codes = codes.substr(3); |
@@ -1049,6 +1098,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
1049 | error_list errors; | 1098 | error_list errors; |
1050 | try { | 1099 | try { |
1051 | State state; | 1100 | State state; |
1101 | state.lax = lax; | ||
1052 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); | 1102 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); |
1053 | if (state.exportCount > 0) { | 1103 | if (state.exportCount > 0) { |
1054 | int index = 0; | 1104 | int index = 0; |
@@ -1086,19 +1136,21 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
1086 | return res; | 1136 | return res; |
1087 | } | 1137 | } |
1088 | 1138 | ||
1089 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes) { | 1139 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes, bool lax) { |
1090 | auto it = _rules.find(astName); | 1140 | auto it = _rules.find(astName); |
1091 | if (it != _rules.end()) { | 1141 | if (it != _rules.end()) { |
1092 | return parse(codes, *it->second); | 1142 | return parse(codes, *it->second, lax); |
1093 | } | 1143 | } |
1094 | return {}; | 1144 | ParseInfo info{}; |
1145 | info.error = ParseInfo::Error{"invalid rule: "s + std::string{astName}, 1, 1}; | ||
1146 | return info; | ||
1095 | } | 1147 | } |
1096 | 1148 | ||
1097 | bool YueParser::match(std::string_view astName, std::string_view codes) { | 1149 | bool YueParser::match(std::string_view astName, std::string_view codes) { |
1098 | auto it = _rules.find(astName); | 1150 | auto it = _rules.find(astName); |
1099 | if (it != _rules.end()) { | 1151 | if (it != _rules.end()) { |
1100 | auto rEnd = rule(*it->second >> eof()); | 1152 | auto rEnd = rule(*it->second >> eof()); |
1101 | return parse(codes, rEnd).node; | 1153 | return parse(codes, rEnd, false).node; |
1102 | } | 1154 | } |
1103 | return false; | 1155 | return false; |
1104 | } | 1156 | } |
@@ -1134,6 +1186,24 @@ void trim(std::string& str) { | |||
1134 | str.erase(0, str.find_first_not_of(" \t\r\n")); | 1186 | str.erase(0, str.find_first_not_of(" \t\r\n")); |
1135 | str.erase(str.find_last_not_of(" \t\r\n") + 1); | 1187 | str.erase(str.find_last_not_of(" \t\r\n") + 1); |
1136 | } | 1188 | } |
1189 | |||
1190 | std::string toLuaDoubleString(const std::string& input) { | ||
1191 | std::string luaStr = "\""; | ||
1192 | for (char c : input) { | ||
1193 | switch (c) { | ||
1194 | case '\"': luaStr += "\\\""; break; | ||
1195 | case '\\': luaStr += "\\\\"; break; | ||
1196 | case '\n': luaStr += "\\n"; break; | ||
1197 | case '\r': luaStr += "\\r"; break; | ||
1198 | case '\t': luaStr += "\\t"; break; | ||
1199 | default: | ||
1200 | luaStr += c; | ||
1201 | break; | ||
1202 | } | ||
1203 | } | ||
1204 | luaStr += "\""; | ||
1205 | return luaStr; | ||
1206 | } | ||
1137 | } // namespace Utils | 1207 | } // namespace Utils |
1138 | 1208 | ||
1139 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { | 1209 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 02292e1..c91e530 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -74,16 +74,16 @@ extern std::unordered_set<std::string> Keywords; | |||
74 | class YueParser { | 74 | class YueParser { |
75 | public: | 75 | public: |
76 | template <class AST> | 76 | template <class AST> |
77 | ParseInfo parse(std::string_view codes) { | 77 | ParseInfo parse(std::string_view codes, bool lax) { |
78 | return parse(codes, getRule<AST>()); | 78 | return parse(codes, getRule<AST>(), lax); |
79 | } | 79 | } |
80 | 80 | ||
81 | ParseInfo parse(std::string_view astName, std::string_view codes); | 81 | ParseInfo parse(std::string_view astName, std::string_view codes, bool lax); |
82 | 82 | ||
83 | template <class AST> | 83 | template <class AST> |
84 | bool match(std::string_view codes) { | 84 | bool match(std::string_view codes) { |
85 | auto rEnd = rule(getRule<AST>() >> eof()); | 85 | auto rEnd = rule(getRule<AST>() >> eof()); |
86 | return parse(codes, rEnd).node; | 86 | return parse(codes, rEnd, false).node; |
87 | } | 87 | } |
88 | 88 | ||
89 | bool match(std::string_view astName, std::string_view codes); | 89 | bool match(std::string_view astName, std::string_view codes); |
@@ -102,13 +102,14 @@ public: | |||
102 | 102 | ||
103 | protected: | 103 | protected: |
104 | YueParser(); | 104 | YueParser(); |
105 | ParseInfo parse(std::string_view codes, rule& r); | 105 | ParseInfo parse(std::string_view codes, rule& r, bool lax); |
106 | bool startWith(std::string_view codes, rule& r); | 106 | bool startWith(std::string_view codes, rule& r); |
107 | 107 | ||
108 | struct State { | 108 | struct State { |
109 | State() { | 109 | State() { |
110 | indents.push(0); | 110 | indents.push(0); |
111 | } | 111 | } |
112 | bool lax = false; | ||
112 | bool exportDefault = false; | 113 | bool exportDefault = false; |
113 | bool exportMacro = false; | 114 | bool exportMacro = false; |
114 | bool exportMetatable = false; | 115 | bool exportMetatable = false; |
@@ -119,10 +120,11 @@ protected: | |||
119 | size_t stringOpen = 0; | 120 | size_t stringOpen = 0; |
120 | std::string buffer; | 121 | std::string buffer; |
121 | std::stack<int> indents; | 122 | std::stack<int> indents; |
122 | std::stack<bool> noDoStack; | 123 | std::vector<bool> noDoStack; |
123 | std::stack<bool> noChainBlockStack; | 124 | std::vector<bool> noChainBlockStack; |
124 | std::stack<bool> noTableBlockStack; | 125 | std::vector<bool> noTableBlockStack; |
125 | std::stack<bool> noForStack; | 126 | std::vector<bool> noForStack; |
127 | std::vector<bool> noUntilStack; | ||
126 | std::unordered_set<std::string> usedNames; | 128 | std::unordered_set<std::string> usedNames; |
127 | }; | 129 | }; |
128 | 130 | ||
@@ -156,7 +158,7 @@ private: | |||
156 | NONE_AST_RULE(invalid_interpolation_error); | 158 | NONE_AST_RULE(invalid_interpolation_error); |
157 | NONE_AST_RULE(confusing_unary_not_error); | 159 | NONE_AST_RULE(confusing_unary_not_error); |
158 | NONE_AST_RULE(table_key_pair_error); | 160 | NONE_AST_RULE(table_key_pair_error); |
159 | NONE_AST_RULE(if_assignment_syntax_error); | 161 | NONE_AST_RULE(assignment_expression_syntax_error); |
160 | 162 | ||
161 | NONE_AST_RULE(inc_exp_level); | 163 | NONE_AST_RULE(inc_exp_level); |
162 | NONE_AST_RULE(dec_exp_level); | 164 | NONE_AST_RULE(dec_exp_level); |
@@ -164,6 +166,7 @@ private: | |||
164 | NONE_AST_RULE(num_char); | 166 | NONE_AST_RULE(num_char); |
165 | NONE_AST_RULE(num_char_hex); | 167 | NONE_AST_RULE(num_char_hex); |
166 | NONE_AST_RULE(num_lit); | 168 | NONE_AST_RULE(num_lit); |
169 | NONE_AST_RULE(num_bin_lit); | ||
167 | NONE_AST_RULE(num_expo); | 170 | NONE_AST_RULE(num_expo); |
168 | NONE_AST_RULE(num_expo_hex); | 171 | NONE_AST_RULE(num_expo_hex); |
169 | NONE_AST_RULE(lj_num); | 172 | NONE_AST_RULE(lj_num); |
@@ -216,6 +219,8 @@ private: | |||
216 | NONE_AST_RULE(enable_for); | 219 | NONE_AST_RULE(enable_for); |
217 | NONE_AST_RULE(enable_fun_lit); | 220 | NONE_AST_RULE(enable_fun_lit); |
218 | NONE_AST_RULE(disable_fun_lit); | 221 | NONE_AST_RULE(disable_fun_lit); |
222 | NONE_AST_RULE(disable_until); | ||
223 | NONE_AST_RULE(enable_until); | ||
219 | NONE_AST_RULE(switch_else); | 224 | NONE_AST_RULE(switch_else); |
220 | NONE_AST_RULE(switch_block); | 225 | NONE_AST_RULE(switch_block); |
221 | NONE_AST_RULE(if_else_if); | 226 | NONE_AST_RULE(if_else_if); |
@@ -283,6 +288,7 @@ private: | |||
283 | NONE_AST_RULE(yue_line_comment); | 288 | NONE_AST_RULE(yue_line_comment); |
284 | NONE_AST_RULE(line); | 289 | NONE_AST_RULE(line); |
285 | NONE_AST_RULE(shebang); | 290 | NONE_AST_RULE(shebang); |
291 | NONE_AST_RULE(lax_line); | ||
286 | 292 | ||
287 | AST_RULE(Num); | 293 | AST_RULE(Num); |
288 | AST_RULE(Name); | 294 | AST_RULE(Name); |
@@ -314,12 +320,14 @@ private: | |||
314 | AST_RULE(ImportAllMacro); | 320 | AST_RULE(ImportAllMacro); |
315 | AST_RULE(ImportTabLit); | 321 | AST_RULE(ImportTabLit); |
316 | AST_RULE(ImportAs); | 322 | AST_RULE(ImportAs); |
323 | AST_RULE(ImportGlobal); | ||
317 | AST_RULE(Import); | 324 | AST_RULE(Import); |
318 | AST_RULE(Label); | 325 | AST_RULE(Label); |
319 | AST_RULE(Goto); | 326 | AST_RULE(Goto); |
320 | AST_RULE(ShortTabAppending); | 327 | AST_RULE(ShortTabAppending); |
321 | AST_RULE(FnArrowBack); | 328 | AST_RULE(FnArrowBack); |
322 | AST_RULE(Backcall); | 329 | AST_RULE(Backcall); |
330 | AST_RULE(SubBackcall); | ||
323 | AST_RULE(PipeBody); | 331 | AST_RULE(PipeBody); |
324 | AST_RULE(ExpListLow); | 332 | AST_RULE(ExpListLow); |
325 | AST_RULE(ExpList); | 333 | AST_RULE(ExpList); |
@@ -358,6 +366,7 @@ private: | |||
358 | AST_RULE(ExpOpValue); | 366 | AST_RULE(ExpOpValue); |
359 | AST_RULE(Exp); | 367 | AST_RULE(Exp); |
360 | AST_RULE(Callable); | 368 | AST_RULE(Callable); |
369 | AST_RULE(ReversedIndex); | ||
361 | AST_RULE(ChainValue); | 370 | AST_RULE(ChainValue); |
362 | AST_RULE(SimpleTable); | 371 | AST_RULE(SimpleTable); |
363 | AST_RULE(SimpleValue); | 372 | AST_RULE(SimpleValue); |
@@ -370,6 +379,11 @@ private: | |||
370 | AST_RULE(DoubleStringInner); | 379 | AST_RULE(DoubleStringInner); |
371 | AST_RULE(DoubleStringContent); | 380 | AST_RULE(DoubleStringContent); |
372 | AST_RULE(DoubleString); | 381 | AST_RULE(DoubleString); |
382 | AST_RULE(YAMLIndent); | ||
383 | AST_RULE(YAMLLineInner); | ||
384 | AST_RULE(YAMLLineContent); | ||
385 | AST_RULE(YAMLLine); | ||
386 | AST_RULE(YAMLMultiline); | ||
373 | AST_RULE(String); | 387 | AST_RULE(String); |
374 | AST_RULE(Parens); | 388 | AST_RULE(Parens); |
375 | AST_RULE(DotChainItem); | 389 | AST_RULE(DotChainItem); |
@@ -426,6 +440,8 @@ private: | |||
426 | AST_RULE(ExpListAssign); | 440 | AST_RULE(ExpListAssign); |
427 | AST_RULE(IfLine); | 441 | AST_RULE(IfLine); |
428 | AST_RULE(WhileLine); | 442 | AST_RULE(WhileLine); |
443 | AST_RULE(Break); | ||
444 | AST_RULE(Continue); | ||
429 | AST_RULE(BreakLoop); | 445 | AST_RULE(BreakLoop); |
430 | AST_RULE(StatementAppendix); | 446 | AST_RULE(StatementAppendix); |
431 | AST_RULE(Statement); | 447 | AST_RULE(Statement); |
@@ -443,6 +459,7 @@ private: | |||
443 | namespace Utils { | 459 | namespace Utils { |
444 | void replace(std::string& str, std::string_view from, std::string_view to); | 460 | void replace(std::string& str, std::string_view from, std::string_view to); |
445 | void trim(std::string& str); | 461 | void trim(std::string& str); |
462 | std::string toLuaDoubleString(const std::string& input); | ||
446 | } // namespace Utils | 463 | } // namespace Utils |
447 | 464 | ||
448 | } // namespace yue | 465 | } // namespace yue |
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp index 7e8e8b7..61e3949 100644 --- a/src/yuescript/yuescript.cpp +++ b/src/yuescript/yuescript.cpp | |||
@@ -93,6 +93,12 @@ static void get_config(lua_State* L, yue::YueConfig& config) { | |||
93 | config.useSpaceOverTab = lua_toboolean(L, -1) != 0; | 93 | config.useSpaceOverTab = lua_toboolean(L, -1) != 0; |
94 | } | 94 | } |
95 | lua_pop(L, 1); | 95 | lua_pop(L, 1); |
96 | lua_pushliteral(L, "lax"); | ||
97 | lua_gettable(L, -2); | ||
98 | if (lua_isboolean(L, -1) != 0) { | ||
99 | config.lax = lua_toboolean(L, -1) != 0; | ||
100 | } | ||
101 | lua_pop(L, 1); | ||
96 | lua_pushliteral(L, "options"); | 102 | lua_pushliteral(L, "options"); |
97 | lua_gettable(L, -2); | 103 | lua_gettable(L, -2); |
98 | if (lua_istable(L, -1) != 0) { | 104 | if (lua_istable(L, -1) != 0) { |
@@ -180,7 +186,7 @@ static int yueformat(lua_State* L) { | |||
180 | tabSize = static_cast<int>(luaL_checkinteger(L, 2)); | 186 | tabSize = static_cast<int>(luaL_checkinteger(L, 2)); |
181 | } | 187 | } |
182 | std::string_view codes(input, len); | 188 | std::string_view codes(input, len); |
183 | auto info = yue::YueParser::shared().parse<yue::File_t>(codes); | 189 | auto info = yue::YueParser::shared().parse<yue::File_t>(codes, false); |
184 | if (info.error) { | 190 | if (info.error) { |
185 | const auto& error = info.error.value(); | 191 | const auto& error = info.error.value(); |
186 | if (!info.codes) { | 192 | if (!info.codes) { |
@@ -201,6 +207,7 @@ static int yueformat(lua_State* L) { | |||
201 | formatter.spaceOverTab = false; | 207 | formatter.spaceOverTab = false; |
202 | } | 208 | } |
203 | auto result = formatter.toString(info.node.get()); | 209 | auto result = formatter.toString(info.node.get()); |
210 | yue::Utils::replace(result, "\n\n", "\n"); | ||
204 | lua_pushlstring(L, result.c_str(), result.size()); | 211 | lua_pushlstring(L, result.c_str(), result.size()); |
205 | return 1; | 212 | return 1; |
206 | } | 213 | } |
@@ -282,8 +289,13 @@ static int yuetoast(lua_State* L) { | |||
282 | ruleName = {name, nameSize}; | 289 | ruleName = {name, nameSize}; |
283 | } | 290 | } |
284 | } | 291 | } |
292 | bool lax = false; | ||
293 | if (!lua_isnoneornil(L, 4)) { | ||
294 | luaL_checktype(L, 4, LUA_TBOOLEAN); | ||
295 | lax = lua_toboolean(L, 4) != 0; | ||
296 | } | ||
285 | auto& yueParser = yue::YueParser::shared(); | 297 | auto& yueParser = yue::YueParser::shared(); |
286 | auto info = ruleName.empty() ? yueParser.parse<yue::File_t>({input, size}) : yueParser.parse(ruleName, {input, size}); | 298 | auto info = ruleName.empty() ? yueParser.parse<yue::File_t>({input, size}, lax) : yueParser.parse(ruleName, {input, size}, lax); |
287 | if (!info.error) { | 299 | if (!info.error) { |
288 | lua_createtable(L, 0, 0); | 300 | lua_createtable(L, 0, 0); |
289 | int tableIndex = lua_gettop(L); | 301 | int tableIndex = lua_gettop(L); |
diff --git a/win-build/Yuescript/Yuescript.vcxproj b/win-build/Yuescript/Yuescript.vcxproj index d073e70..87e13ce 100644 --- a/win-build/Yuescript/Yuescript.vcxproj +++ b/win-build/Yuescript/Yuescript.vcxproj | |||
@@ -215,6 +215,7 @@ | |||
215 | <Link> | 215 | <Link> |
216 | <SubSystem>Console</SubSystem> | 216 | <SubSystem>Console</SubSystem> |
217 | <GenerateDebugInformation>true</GenerateDebugInformation> | 217 | <GenerateDebugInformation>true</GenerateDebugInformation> |
218 | <AdditionalOptions>/STACK:2097152 %(AdditionalOptions)</AdditionalOptions> | ||
218 | </Link> | 219 | </Link> |
219 | </ItemDefinitionGroup> | 220 | </ItemDefinitionGroup> |
220 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug53|x64'"> | 221 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug53|x64'"> |
@@ -230,6 +231,7 @@ | |||
230 | <Link> | 231 | <Link> |
231 | <SubSystem>Console</SubSystem> | 232 | <SubSystem>Console</SubSystem> |
232 | <GenerateDebugInformation>true</GenerateDebugInformation> | 233 | <GenerateDebugInformation>true</GenerateDebugInformation> |
234 | <AdditionalOptions>/STACK:2097152 %(AdditionalOptions)</AdditionalOptions> | ||
233 | </Link> | 235 | </Link> |
234 | </ItemDefinitionGroup> | 236 | </ItemDefinitionGroup> |
235 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | 237 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
@@ -287,6 +289,7 @@ | |||
287 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | 289 | <EnableCOMDATFolding>true</EnableCOMDATFolding> |
288 | <OptimizeReferences>true</OptimizeReferences> | 290 | <OptimizeReferences>true</OptimizeReferences> |
289 | <GenerateDebugInformation>true</GenerateDebugInformation> | 291 | <GenerateDebugInformation>true</GenerateDebugInformation> |
292 | <AdditionalOptions>/STACK:2097152 %(AdditionalOptions)</AdditionalOptions> | ||
290 | </Link> | 293 | </Link> |
291 | </ItemDefinitionGroup> | 294 | </ItemDefinitionGroup> |
292 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release53|x64'"> | 295 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release53|x64'"> |
@@ -306,6 +309,7 @@ | |||
306 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | 309 | <EnableCOMDATFolding>true</EnableCOMDATFolding> |
307 | <OptimizeReferences>true</OptimizeReferences> | 310 | <OptimizeReferences>true</OptimizeReferences> |
308 | <GenerateDebugInformation>true</GenerateDebugInformation> | 311 | <GenerateDebugInformation>true</GenerateDebugInformation> |
312 | <AdditionalOptions>/STACK:2097152 %(AdditionalOptions)</AdditionalOptions> | ||
309 | </Link> | 313 | </Link> |
310 | </ItemDefinitionGroup> | 314 | </ItemDefinitionGroup> |
311 | <ItemGroup> | 315 | <ItemGroup> |