aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdoc/docs/doc/README.md574
-rwxr-xr-xdoc/docs/zh/doc/README.md602
-rw-r--r--makefile2
-rw-r--r--spec/inputs/backcall.yue4
-rw-r--r--spec/inputs/destructure.yue40
-rw-r--r--spec/inputs/global.yue6
-rw-r--r--spec/inputs/import.yue10
-rw-r--r--spec/inputs/lists.yue47
-rw-r--r--spec/inputs/loops.yue52
-rw-r--r--spec/inputs/macro.yue54
-rw-r--r--spec/inputs/macro_export.yue31
-rw-r--r--spec/inputs/macro_teal.yue13
-rw-r--r--spec/inputs/macro_todo.yue7
-rw-r--r--spec/inputs/props.yue61
-rw-r--r--spec/inputs/string.yue73
-rw-r--r--spec/inputs/switch.yue125
-rw-r--r--spec/inputs/tables.yue18
-rw-r--r--spec/inputs/try_catch.yue122
-rw-r--r--spec/inputs/unicode/destructure.yue2
-rw-r--r--spec/inputs/unicode/macro_export.yue4
-rw-r--r--spec/inputs/unicode/with.yue24
-rw-r--r--spec/inputs/with.yue42
-rw-r--r--spec/outputs/5.1/literals.lua44
-rw-r--r--spec/outputs/5.1/loops.lua132
-rw-r--r--spec/outputs/5.1/try_catch.lua265
-rw-r--r--spec/outputs/assign.lua6
-rw-r--r--spec/outputs/codes_from_doc.lua838
-rw-r--r--spec/outputs/codes_from_doc_zh.lua838
-rw-r--r--spec/outputs/comprehension.lua10
-rw-r--r--spec/outputs/destructure.lua90
-rw-r--r--spec/outputs/global.lua25
-rw-r--r--spec/outputs/import.lua10
-rw-r--r--spec/outputs/lists.lua215
-rw-r--r--spec/outputs/loops.lua132
-rw-r--r--spec/outputs/macro.lua15
-rw-r--r--spec/outputs/props.lua240
-rw-r--r--spec/outputs/string.lua41
-rw-r--r--spec/outputs/switch.lua362
-rw-r--r--spec/outputs/tables.lua22
-rw-r--r--spec/outputs/try_catch.lua266
-rw-r--r--spec/outputs/unicode/assign.lua6
-rw-r--r--spec/outputs/unicode/comprehension.lua10
-rw-r--r--spec/outputs/unicode/lists.lua23
-rw-r--r--spec/outputs/unicode/loops.lua4
-rw-r--r--spec/outputs/unicode/macro.lua48
-rw-r--r--spec/outputs/unicode/multiline_chain.lua6
-rw-r--r--spec/outputs/unicode/syntax.lua6
-rw-r--r--spec/outputs/unicode/vararg.lua28
-rw-r--r--spec/outputs/upvalue_func.lua48
-rw-r--r--spec/outputs/vararg.lua28
-rw-r--r--spec/outputs/with.lua62
-rw-r--r--src/3rdParty/efsw/FileWatcherGeneric.cpp2
-rw-r--r--src/yuescript/yue_ast.cpp201
-rw-r--r--src/yuescript/yue_ast.h100
-rw-r--r--src/yuescript/yue_compiler.cpp1208
-rw-r--r--src/yuescript/yue_compiler.h1
-rw-r--r--src/yuescript/yue_parser.cpp162
-rw-r--r--src/yuescript/yue_parser.h36
-rw-r--r--src/yuescript/yuescript.cpp16
-rw-r--r--win-build/Yuescript/Yuescript.vcxproj4
60 files changed, 6732 insertions, 731 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
19import "yue" as :p, :to_lua 19import p, to_lua from "yue"
20 20
21-- object literals 21-- object literals
22inventory = 22inventory =
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
33map = (arr, action) ->
34 [action item for item in *arr]
35
36filter = (arr, cond) ->
37 [item for item in *arr when cond item]
38
39reduce = (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
54import "yue" as :p, :to_lua 64import p, to_lua from "yue"
55 65
56-- object literals 66-- object literals
57inventory = 67inventory =
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
78map = (arr, action) ->
79 [action item for item in *arr]
80
81filter = (arr, cond) ->
82 [item for item in *arr when cond item]
83
84reduce = (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&emsp;Use YueScript module in Lua: 153&emsp;Use YueScript module in Lua:
134 154
135* **Case 1** 155* **Case 1**
136Require "your_yuescript_entry.yue" in Lua. 156Require "your_yuescript_entry.yue" in Lua.
137```Lua 157```Lua
138require("yue")("your_yuescript_entry") 158require("yue")("your_yuescript_entry")
139``` 159```
140&emsp;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&emsp;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**
143Require YueScript module and rewite message by hand. 163Require YueScript module and rewite message by hand.
144```lua 164```lua
145local yue = require("yue") 165local yue = require("yue")
@@ -151,7 +171,7 @@ end, function(err)
151end) 171end)
152``` 172```
153 173
154* **Case 3** 174* **Case 3**
155Use the YueScript compiler function in Lua. 175Use the YueScript compiler function in Lua.
156```lua 176```lua
157local yue = require("yue") 177local 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&emsp;&emsp;Use cases: 226&emsp;&emsp;Use cases:
207&emsp;&emsp;Recursively compile every YueScript file with extension **.yue** under current path: **yue .** 227&emsp;&emsp;Recursively compile every YueScript file with extension **.yue** under current path: **yue .**
208&emsp;&emsp;Compile and save results to a target path: **yue -t /target/path/ .** 228&emsp;&emsp;Compile and save results to a target path: **yue -t /target/path/ .**
209&emsp;&emsp;Compile and reserve debug info: **yue -l .** 229&emsp;&emsp;Compile and reserve debug info: **yue -l .**
210&emsp;&emsp;Compile and generate minified codes: **yue -m .** 230&emsp;&emsp;Compile and generate minified codes: **yue -m .**
211&emsp;&emsp;Execute raw codes: **yue -e 'print 123'** 231&emsp;&emsp;Execute raw codes: **yue -e 'print 123'**
212&emsp;&emsp;Execute a YueScript file: **yue -e main.yue** 232&emsp;&emsp;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
449You 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
452macro printNumAndStr = (num `Num, str `String) -> |
453 print(
454 #{num}
455 #{str}
456 )
457
458$printNumAndStr 123, "hello"
459```
460<YueDisplay>
461<pre>
462macro printNumAndStr = (num `Num, str `String) -> |
463 print(
464 #{num}
465 #{str}
466 )
467
468$printNumAndStr 123, "hello"
469</pre>
470</YueDisplay>
471
472If 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
475macro 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>
484macro 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
493For 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
429All 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. 497All 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
639You can use the **#** operator to get the last elements of a table.
640
641```moonscript
642last = data.items[#]
643second_last = data.items[#-1]
644```
645<YueDisplay>
646<pre>
647last = data.items[#]
648second_last = data.items[#-1]
649</pre>
650</YueDisplay>
651
569### Metatable 652### Metatable
570 653
571The **<>** operator can be used as a shortcut for metatable manipulation. 654The **<>** operator can be used as a shortcut for metatable manipulation.
572 655
573* **Metatable Creation** 656* **Metatable Creation**
574Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. 657Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**.
575 658
576```moonscript 659```moonscript
@@ -606,7 +689,7 @@ close _ = &lt;close&gt;: -> print "out of scope"
606</pre> 689</pre>
607</YueDisplay> 690</YueDisplay>
608 691
609* **Metatable Accessing** 692* **Metatable Accessing**
610Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. 693Accessing 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**
634Destruct metatable with metamethod key surrounded by **<>**. 717Destruct 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
735You 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. 818You 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
737list = 822list =
738 * 1 823 * 1
739 * 2 824 * 2
740 * 3 825 * 3
741 826
827-- function call with implicit object
742func 828func
743 * 1 829 * 1
744 * 2 830 * 2
745 * 3 831 * 3
746 832
833-- return with implicit object
834f = ->
835 return
836 * 1
837 * 2
838 * 3
839
840-- table with implicit object
747tb = 841tb =
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
770list = 865list =
771 * 1 866 * 1
772 * 2 867 * 2
773 * 3 868 * 3
774 869
870-- function call with implicit object
775func 871func
776 * 1 872 * 1
777 * 2 873 * 2
778 * 3 874 * 3
779 875
876-- return with implicit object
877f = ->
878 return
879 * 1
880 * 2
881 * 3
882
883-- table with implicit object
780tb = 884tb =
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
861The export statement offers a concise way to define modules. 965The export statement offers a concise way to define modules.
862 966
863* **Named Export** 967* **Named Export**
864Named export will define a local variable as well as adding a field in the exported table. 968Named 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**
928Unnamed export will add the target item into the array part of the exported table. 1032Unnamed 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**
958Using the **default** keyword in export statement to replace the exported table with any thing. 1062Using 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
1205It’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: 1309It'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
1355You 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
1358orders = ["first", "second", "third", "fourth", "last"]
1359[first, ...bulk, last] = orders
1360print first -- prints: first
1361print bulk -- prints: {"second", "third", "fourth"}
1362print last -- prints: last
1363```
1364<YueDisplay>
1365<pre>
1366orders = ["first", "second", "third", "fourth", "last"]
1367[first, ...bulk, last] = orders
1368print first -- prints: first
1369print bulk -- prints: {"second", "third", "fourth"}
1370print last -- prints: last
1371</pre>
1372</YueDisplay>
1373
1374The 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
1251Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: 1401Destructuring 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
1633a, b, c = try? func!
1634
1635-- with nil coalescing operator
1636a = (try? func!) ?? "default"
1637
1638-- as function argument
1639f try? func!
1640
1641-- with catch block
1642f try?
1643 print 123
1644 func!
1645catch e
1646 print e
1647 e
1648```
1649<YueDisplay>
1650<pre>
1651a, b, c = try? func!
1652
1653-- with nil coalescing operator
1654a = (try? func!) ?? "default"
1655
1656-- as function argument
1657f try? func!
1658
1659-- with catch block
1660f try?
1661 print 123
1662 func!
1663catch e
1664 print e
1665 e
1666</pre>
1667</YueDisplay>
1668
1478## Attributes 1669## Attributes
1479 1670
1480Syntax 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. 1671Syntax 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
1697You can also declare a global variable to be `const`.
1698
1699```moonscript
1700global const Constant = 123
1701-- Constant = 1
1702```
1703<YueDisplay>
1704<pre>
1705global const Constant = 123
1706-- Constant = 1
1707</pre>
1708</YueDisplay>
1709
1506## Literals 1710## Literals
1507 1711
1508All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. 1712All 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
1536integer = 1_000_000 1740integer = 1_000_000
1537hex = 0xEF_BB_BF 1741hex = 0xEF_BB_BF
1742binary = 0B10011
1538``` 1743```
1539<YueDisplay> 1744<YueDisplay>
1540 1745
1541<pre> 1746<pre>
1542integer = 1_000_000 1747integer = 1_000_000
1543hex = 0xEF_BB_BF 1748hex = 0xEF_BB_BF
1749binary = 0B10011
1750</pre>
1751</YueDisplay>
1752
1753### YAML Multiline String
1754
1755The `|` prefix introduces a YAML-style multiline string literal:
1756
1757```moonscript
1758str = |
1759 key: value
1760 list:
1761 - item1
1762 - #{expr}
1763```
1764<YueDisplay>
1765<pre>
1766str = |
1767 key: value
1768 list:
1769 - item1
1770 - #{expr}
1771</pre>
1772</YueDisplay>
1773
1774This 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
1776YAML 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
1779fn = ->
1780 str = |
1781 foo:
1782 bar: baz
1783 return str
1784```
1785<YueDisplay>
1786<pre>
1787fn = ->
1788 str = |
1789 foo:
1790 bar: baz
1791 return str
1792</pre>
1793</YueDisplay>
1794
1795Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures.
1796
1797All 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
1800str = |
1801 path: "C:\Program Files\App"
1802 note: 'He said: "#{Hello}!"'
1803```
1804<YueDisplay>
1805<pre>
1806str = |
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
1905If you wish to have further code after your backcalls, you can set them aside with a do statement. 2170If 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
1908result, msg = do 2173result, 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
1913print result, msg 2178print result, msg
1914``` 2179```
1915<YueDisplay> 2180<YueDisplay>
1916<pre> 2181<pre>
1917result, msg = do 2182result, 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
1922print result, msg 2187print 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
2516Both 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
2520slice = [item for item in *items[-4,-1]]
2521```
2522<YueDisplay>
2523<pre>
2524-- take the last 4 items
2525slice = [item for item in *items[-4,-1]]
2526</pre>
2527</YueDisplay>
2528
2529The step size can also be negative, which means that the items are taken in reverse order.
2530
2531```moonscript
2532reverse_slice = [item for item in *items[-1,1,-1]]
2533```
2534<YueDisplay>
2535<pre>
2536reverse_slice = [item for item in *items[-1,1,-1]]
2537</pre>
2538</YueDisplay>
2539
2540#### Slicing Expression
2541
2542Slicing 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
2546sub_list = items[2, 4]
2547```
2548<YueDisplay>
2549<pre>
2550-- take the 2nd and 4th items as a new list
2551sub_list = items[2, 4]
2552</pre>
2553</YueDisplay>
2554
2251## For Loop 2555## For Loop
2252 2556
2253There are two for loop forms, just like in Lua. A numeric one and a generic one: 2557There 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
2631In 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
2633For example, to find the first number greater than 10:
2634
2635```moonscript
2636first_large = for n in *numbers
2637 break n if n > 10
2638```
2639<YueDisplay>
2640<pre>
2641first_large = for n in *numbers
2642 break n if n > 10
2643</pre>
2644</YueDisplay>
2645
2646This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions.
2647
2327You can also filter values by combining the for loop expression with the continue statement. 2648You can also filter values by combining the for loop expression with the continue statement.
2328 2649
2329For 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. 2650For 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
2348This is done to avoid the needless creation of tables for functions that don’t need to return the results of the loop. 2669This 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
2627The 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. 2948The 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
2630name = "Dan" 2951switch name := "Dan"
2631switch 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>
2641name = "Dan" 2961switch name := "Dan"
2642switch 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
2679We 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. 2998We 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
2682msg = switch math.random(1, 5) 3001msg = switch math.random(1, 5)
@@ -2722,7 +3041,7 @@ else
2722</pre> 3041</pre>
2723</YueDisplay> 3042</YueDisplay>
2724 3043
2725It 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. 3044It 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
3104You can also match against array elements, table fields, and even nested structures with array or table literals.
3105
3106Match against array elements.
3107
3108```moonscript
3109switch 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>
3119switch 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
3129Match against table fields with destructuring.
3130
3131```moonscript
3132switch 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>
3142switch 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
3152Match against nested table structures.
3153
3154```moonscript
3155switch 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>
3165switch 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
3175Match against array of tables.
3176
3177```moonscript
3178switch 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>
3189switch 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
3200Match against a list and capture a range of elements.
3201
3202```moonscript
3203segments = ["admin", "users", "logs", "view"]
3204switch 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>
3212segments = ["admin", "users", "logs", "view"]
3213switch 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
2787In 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. 3223In 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
2914Here we extend our Inventory class, and limit the amount of items it can carry. 3350Here we extend our Inventory class, and limit the amount of items it can carry.
2915 3351
2916In 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. 3352In 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
2918Whenever 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. 3354Whenever 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
3001The 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. 3437The 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
3003The 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. 3439The 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
3005A 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. 3441A 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
3007The 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. 3443The 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
3009It 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. 3445It 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
3011The class object has a couple special properties: 3447The 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
3082The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua’s colon syntax. 3518The 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
3095In 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. 3531In 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
3097Here is an alternative way to create a class variable compared to what’s described above: 3533Here is an alternative way to create a class variable compared to what's described above:
3098 3534
3099```moonscript 3535```moonscript
3100class Things 3536class Things
@@ -3360,19 +3796,19 @@ In this usage, with can be seen as a special form of the K combinator.
3360The expression in the with statement can also be an assignment, if you want to give a name to the expression. 3796The 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
3363with str = "Hello" 3799with 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>
3369with str = "Hello" 3805with 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
3375Accessing special keys with `[]` in a `with` statement. 3811You can access special keys with `[]` in a `with` statement.
3376 3812
3377```moonscript 3813```moonscript
3378with tb 3814with 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
3837with? obj
3838 print obj.name
3839```
3840<YueDisplay>
3841<pre>
3842with? 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
3418YueScript’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. 3866YueScript'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
3421counter = do 3869counter = do
@@ -3541,7 +3989,7 @@ print i -- will print 0
3541</pre> 3989</pre>
3542</YueDisplay> 3990</YueDisplay>
3543 3991
3544In 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. 3992In 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
3546It 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. 3994It 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 754566c..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-- ε―Όε…₯语法
19import "yue" as :p, :to_lua 19import p, to_lua from "yue"
20 20
21-- 隐式对豑 21-- 隐式对豑
22inventory = 22inventory =
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-- εˆ—θ‘¨ζŽ¨ε―Ό
33map = (arr, action) ->
34 [action item for item in *arr]
35
36filter = (arr, cond) ->
37 [item for item in *arr when cond item]
38
39reduce = (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-- ε―Όε…₯语法
54import "yue" as :p, :to_lua 64import p, to_lua from "yue"
55 65
56-- 隐式对豑 66-- 隐式对豑
57inventory = 67inventory =
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-- εˆ—θ‘¨ζŽ¨ε―Ό
78map = (arr, action) ->
79 [action item for item in *arr]
80
81filter = (arr, cond) ->
82 [item for item in *arr when cond item]
83
84reduce = (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&emsp;您可δ»₯δΈ‹θ½½ι’„ηΌ–θ―‘ηš„δΊŒθΏ›εˆΆη¨‹εΊοΌŒεŒ…ζ‹¬ε…ΌεΉδΈεŒ Lua η‰ˆζœ¬ηš„δΊŒθΏ›εˆΆε―ζ‰§θ‘Œζ–‡δ»Άε’ŒεΊ“ζ–‡δ»Άγ€‚ 145&emsp;你可δ»₯δΈ‹θ½½ι’„ηΌ–θ―‘ηš„δΊŒθΏ›εˆΆη¨‹εΊοΌŒεŒ…ζ‹¬ε…ΌεΉδΈεŒ Lua η‰ˆζœ¬ηš„δΊŒθΏ›εˆΆε―ζ‰§θ‘Œζ–‡δ»Άε’ŒεΊ“ζ–‡δ»Άγ€‚
126 146
127&emsp;在[θΏ™ι‡Œ](https://github.com/IppClub/YueScript/releases)δΈ‹θ½½ι’„ηΌ–θ―‘ηš„δΊŒθΏ›εˆΆη¨‹εΊγ€‚ 147&emsp;在[θΏ™ι‡Œ](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
138require("yue")("δ½ ηš„θ„šζœ¬ε…₯口文仢") 158require("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
145local yue = require("yue") 165local yue = require("yue")
@@ -151,7 +171,7 @@ end, function(err)
151end) 171end)
152``` 172```
153 173
154* **用法 3** 174* **用法 3**
155在LuaδΈ­δ½Ώη”¨ζœˆδΉ‹θ„šζœ¬ηΌ–θ―‘ε™¨εŠŸθƒ½γ€‚ 175在LuaδΈ­δ½Ώη”¨ζœˆδΉ‹θ„šζœ¬ηΌ–θ―‘ε™¨εŠŸθƒ½γ€‚
156```lua 176```lua
157local yue = require("yue") 177local yue = require("yue")
@@ -202,12 +222,12 @@ f!
202 δΈζ·»εŠ δ»»δ½•ι€‰ι‘Ήζ‰§θ‘Œε‘½δ»€ε―δ»₯θΏ›ε…₯REPL樑式, 222 δΈζ·»εŠ δ»»δ½•ι€‰ι‘Ήζ‰§θ‘Œε‘½δ»€ε―δ»₯θΏ›ε…₯REPL樑式,
203 εœ¨ε•θ‘ŒθΎ“ε…₯符号 '$' 幢捒葌后,可δ»₯εΌ€ε§‹ζˆ–ζ˜―εœζ­’ε€šθ‘ŒθΎ“ε…₯樑式 223 εœ¨ε•θ‘ŒθΎ“ε…₯符号 '$' 幢捒葌后,可δ»₯εΌ€ε§‹ζˆ–ζ˜―εœζ­’ε€šθ‘ŒθΎ“ε…₯樑式
204``` 224```
205&emsp;&emsp;δ½Ώη”¨ζ‘ˆδΎ‹οΌš 225&emsp;&emsp;δ½Ώη”¨ζ‘ˆδΎ‹οΌš
206&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** ηš„ζ―δΈͺζœˆδΉ‹θ„šζœ¬ζ–‡δ»ΆοΌš **yue .** 226&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** ηš„ζ―δΈͺζœˆδΉ‹θ„šζœ¬ζ–‡δ»ΆοΌš **yue .**
207&emsp;&emsp;ηΌ–θ―‘εΉΆε°†η»“ζžœδΏε­˜εˆ°η›ζ ‡θ·―εΎ„οΌš **yue -t /target/path/ .** 227&emsp;&emsp;ηΌ–θ―‘εΉΆε°†η»“ζžœδΏε­˜εˆ°η›ζ ‡θ·―εΎ„οΌš **yue -t /target/path/ .**
208&emsp;&emsp;ηΌ–θ―‘εΉΆδΏη•™θ°ƒθ―•δΏ‘ζ―οΌš **yue -l .** 228&emsp;&emsp;ηΌ–θ―‘εΉΆδΏη•™θ°ƒθ―•δΏ‘ζ―οΌš **yue -l .**
209&emsp;&emsp;ηΌ–θ―‘εΉΆη”ŸζˆεŽ‹ηΌ©δ»£η οΌš **yue -m .** 229&emsp;&emsp;ηΌ–θ―‘εΉΆη”ŸζˆεŽ‹ηΌ©δ»£η οΌš **yue -m .**
210&emsp;&emsp;η›΄ζŽ₯ζ‰§θ‘Œδ»£η οΌš **yue -e 'print 123'** 230&emsp;&emsp;η›΄ζŽ₯ζ‰§θ‘Œδ»£η οΌš **yue -e 'print 123'**
211&emsp;&emsp;ζ‰§θ‘ŒδΈ€δΈͺζœˆδΉ‹θ„šζœ¬ζ–‡δ»ΆοΌš **yue -e main.yue** 231&emsp;&emsp;ζ‰§θ‘ŒδΈ€δΈͺζœˆδΉ‹θ„šζœ¬ζ–‡δ»ΆοΌš **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
339export macro map = (items, action) -> "[#{action} for _ in *#{items}]" 359export 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
450macro printNumAndStr = (num `Num, str `String) -> |
451 print(
452 #{num}
453 #{str}
454 )
455
456$printNumAndStr 123, "hello"
457```
458<YueDisplay>
459<pre>
460macro 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
473macro 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>
482macro 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
427Luaηš„ζ‰€ζœ‰δΊŒε…ƒε’ŒδΈ€ε…ƒζ“δ½œη¬¦εœ¨ζœˆδΉ‹θ„šζœ¬δΈ­ιƒ½ζ˜―ε―η”¨ηš„γ€‚ζ­€ε€–οΌŒ**!=** 符号是 **~=** ηš„εˆ«εοΌŒθ€Œ **\\** ζˆ– **::** ε‡ε―η”¨δΊŽηΌ–ε†™ι“ΎεΌε‡½ζ•°θ°ƒη”¨οΌŒε¦‚ε†™δ½œ `tb\func!` ζˆ– `tb::func!`γ€‚ζ­€ε€–ζœˆδΉ‹θ„šζœ¬θΏ˜ζδΎ›δΊ†δΈ€δΊ›ε…Άδ»–η‰ΉζŠηš„ζ“δ½œη¬¦οΌŒδ»₯ηΌ–ε†™ζ›΄ε…·θ‘¨θΎΎεŠ›ηš„δ»£η γ€‚ 495Luaηš„ζ‰€ζœ‰δΊŒε…ƒε’ŒδΈ€ε…ƒζ“δ½œη¬¦εœ¨ζœˆδΉ‹θ„šζœ¬δΈ­ιƒ½ζ˜―ε―η”¨ηš„γ€‚ζ­€ε€–οΌŒ**!=** 符号是 **~=** ηš„εˆ«εοΌŒθ€Œ **\\** ζˆ– **::** ε‡ε―η”¨δΊŽηΌ–ε†™ι“ΎεΌε‡½ζ•°θ°ƒη”¨οΌŒε¦‚ε†™δ½œ `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
445print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 513print 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
534parts = 602parts =
@@ -565,11 +633,26 @@ merge = {...a, ...b}
565</pre> 633</pre>
566</YueDisplay> 634</YueDisplay>
567 635
636### 葨反向紒引
637
638你可δ»₯使用 **#** ζ“δ½œη¬¦ζ₯εε‘η΄’εΌ•θ‘¨δΈ­ηš„ε…ƒη΄ γ€‚
639
640```moonscript
641last = data.items[#]
642second_last = data.items[#-1]
643```
644<YueDisplay>
645<pre>
646last = data.items[#]
647second_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 _ = &lt;close&gt;: -> 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-- θ΅‹ε€Όζ—Άδ½Ώη”¨ιšεΌε―Ήθ±‘
736list = 821list =
737 * 1 822 * 1
738 * 2 823 * 2
739 * 3 824 * 3
740 825
826-- ε‡½ζ•°θ°ƒη”¨ζ—Άδ½Ώη”¨ιšεΌε―Ήθ±‘
741func 827func
742 * 1 828 * 1
743 * 2 829 * 2
744 * 3 830 * 3
745 831
832-- θΏ”ε›žζ—Άδ½Ώη”¨ιšεΌε―Ήθ±‘
833f = ->
834 return
835 * 1
836 * 2
837 * 3
838
839-- θ‘¨ζ Όζ—Άδ½Ώη”¨ιšεΌε―Ήθ±‘
746tb = 840tb =
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-- θ΅‹ε€Όζ—Άδ½Ώη”¨ιšεΌε―Ήθ±‘
769list = 863list =
770 * 1 864 * 1
771 * 2 865 * 2
772 * 3 866 * 3
773 867
868-- ε‡½ζ•°θ°ƒη”¨ζ—Άδ½Ώη”¨ιšεΌε―Ήθ±‘
774func 869func
775 * 1 870 * 1
776 * 2 871 * 2
777 * 3 872 * 3
778 873
874-- θΏ”ε›žζ—Άδ½Ώη”¨ιšεΌε―Ήθ±‘
875f = ->
876 return
877 * 1
878 * 2
879 * 3
880
881-- θ‘¨ζ Όζ—Άδ½Ώη”¨ιšεΌε―Ήθ±‘
779tb = 882tb =
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
1356orders = ["first", "second", "third", "fourth", "last"]
1357[first, ...bulk, last] = orders
1358print first -- 打印: first
1359print bulk -- 打印: {"second", "third", "fourth"}
1360print last -- 打印: last
1361```
1362<YueDisplay>
1363<pre>
1364orders = ["first", "second", "third", "fourth", "last"]
1365[first, ...bulk, last] = orders
1366print first -- 打印: first
1367print bulk -- 打印: {"second", "third", "fourth"}
1368print 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
1253tuples = [ 1402tuples = [
@@ -1322,7 +1471,7 @@ print "ε₯½ηš„"
1322 1471
1323### While θ΅‹ε€Ό 1472### While θ΅‹ε€Ό
1324 1473
1325您可δ»₯在 while εΎͺηŽ―δΈ­εŒζ ·δ½Ώη”¨θ΅‹ε€Όζ₯θŽ·ε–εΎͺηŽ―ζ‘δ»Άηš„ε€Όγ€‚ 1474你可δ»₯在 while εΎͺηŽ―δΈ­εŒζ ·δ½Ώη”¨θ΅‹ε€Όζ₯θŽ·ε–εΎͺηŽ―ζ‘δ»Άηš„ε€Όγ€‚
1326```moonscript 1475```moonscript
1327while byte := stream\read_one! 1476while 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
1343list = [1, 2, 3, 4, 5] 1492list = [1, 2, 3, 4, 5]
1344fn = (ok) -> ok, table.unpack list 1493fn = (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
1631a, b, c = try? func!
1632
1633-- δΈŽη©Ίε€ΌεˆεΉΆθΏη—符一衷使用
1634a = (try? func!) ?? "default"
1635
1636-- δ½œδΈΊε‡½ζ•°ε‚ζ•°
1637f try? func!
1638
1639-- εΈ¦ catch ε—ηš„ try!
1640f try?
1641 print 123
1642 func!
1643catch e
1644 print e
1645 e
1646```
1647<YueDisplay>
1648<pre>
1649a, b, c = try? func!
1650
1651-- δΈŽη©Ίε€ΌεˆεΉΆθΏη—符一衷使用
1652a = (try? func!) ?? "default"
1653
1654-- δ½œδΈΊε‡½ζ•°ε‚ζ•°
1655f try? func!
1656
1657-- εΈ¦ catch ε—ηš„ try!
1658f try?
1659 print 123
1660 func!
1661catch 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
1698global const Constant = 123
1699-- Constant = 1
1700```
1701<YueDisplay>
1702<pre>
1703global const Constant = 123
1704-- Constant = 1
1705</pre>
1706</YueDisplay>
1707
1505## 字青量 1708## 字青量
1506 1709
1507LuaδΈ­ηš„ζ‰€ζœ‰εŸΊζœ¬ε­—ι’ι‡ιƒ½ε―δ»₯εœ¨ζœˆδΉ‹θ„šζœ¬δΈ­δ½Ώη”¨γ€‚εŒ…ζ‹¬ζ•°ε­—γ€ε­—η¬¦δΈ²γ€εΈƒε°”ε€Όε’Œ**nil**。 1710LuaδΈ­ηš„ζ‰€ζœ‰εŸΊζœ¬ε­—ι’ι‡ιƒ½ε―δ»₯εœ¨ζœˆδΉ‹θ„šζœ¬δΈ­δ½Ώη”¨γ€‚εŒ…ζ‹¬ζ•°ε­—γ€ε­—η¬¦δΈ²γ€εΈƒε°”ε€Όε’Œ**nil**。
@@ -1529,17 +1732,78 @@ print "ζˆ‘ζœ‰#{math.random! * 100}%ηš„ζŠŠζ‘γ€‚"
1529 1732
1530### 数字字青量 1733### 数字字青量
1531 1734
1532您可δ»₯εœ¨ζ•°ε­—ε­—ι’ι‡δΈ­δ½Ώη”¨δΈ‹εˆ’ηΊΏζ₯ε’žεŠ ε―θ―»ζ€§γ€‚ 1735你可δ»₯εœ¨ζ•°ε­—ε­—ι’ι‡δΈ­δ½Ώη”¨δΈ‹εˆ’ηΊΏζ₯ε’žεŠ ε―θ―»ζ€§γ€‚
1533 1736
1534```moonscript 1737```moonscript
1535integer = 1_000_000 1738integer = 1_000_000
1536hex = 0xEF_BB_BF 1739hex = 0xEF_BB_BF
1740binary = 0B10011
1537``` 1741```
1538<YueDisplay> 1742<YueDisplay>
1539 1743
1540<pre> 1744<pre>
1541integer = 1_000_000 1745integer = 1_000_000
1542hex = 0xEF_BB_BF 1746hex = 0xEF_BB_BF
1747binary = 0B10011
1748</pre>
1749</YueDisplay>
1750
1751### YAML ι£Žζ Όε­—η¬¦δΈ²
1752
1753使用 `|` 前缀标θ°δΈ€δΈͺ倚葌 YAML ι£Žζ Όε­—η¬¦δΈ²οΌš
1754
1755```moonscript
1756str = |
1757 key: value
1758 list:
1759 - item1
1760 - #{expr}
1761```
1762<YueDisplay>
1763<pre>
1764str = |
1765 key: value
1766 list:
1767 - item1
1768 - #{expr}
1769</pre>
1770</YueDisplay>
1771
1772ε…Άζ•ˆζžœη±»δΌΌδΊŽεŽŸη”Ÿ Lua ηš„ε€šθ‘Œζ‹ΌζŽ₯οΌŒζ‰€ζœ‰ζ–‡ζœ¬οΌˆε«ζ’θ‘ŒοΌ‰ε°†θ’«δΏη•™δΈ‹ζ₯οΌŒεΉΆζ”―ζŒ `#{...}` θ―­ζ³•οΌŒι€šθΏ‡ `tostring(expr)` 插ε…₯θ‘¨θΎΎεΌη»“ζžœγ€‚
1773
1774YAML ι£Žζ Όηš„ε€šθ‘Œε­—η¬¦δΈ²δΌšθ‡ͺεŠ¨ζ£€ζ΅‹ι¦–θ‘ŒεŽζœ€ε°ηš„ε…¬ε…±ηΌ©θΏ›οΌŒεΉΆδ»Žζ‰€ζœ‰θ‘ŒδΈ­εˆ ι™€θ―₯前缀空白字符。这θ©δ½ ε―δ»₯εœ¨δ»£η δΈ­ε―Ήι½ζ–‡ζœ¬οΌŒδ½†θΎ“ε‡Ίε­—η¬¦δΈ²δΈδΌšεΈ¦ε€šδ½™ηΌ©θΏ›γ€‚
1775
1776```moonscript
1777fn = ->
1778 str = |
1779 foo:
1780 bar: baz
1781 return str
1782```
1783<YueDisplay>
1784<pre>
1785fn = ->
1786 str = |
1787 foo:
1788 bar: baz
1789 return str
1790</pre>
1791</YueDisplay>
1792
1793θΎ“ε‡Ίε­—η¬¦δΈ²δΈ­ηš„ foo: ε―Ήι½εˆ°θ‘Œι¦–οΌŒδΈδΌšεΈ¦ζœ‰ε‡½ζ•°ηΌ©θΏ›η©Ίζ Όγ€‚δΏη•™ε†…ιƒ¨ηΌ©θΏ›ηš„η›Έε―Ήη»“ζž„οΌŒι€‚εˆδΉ¦ε†™η»“ζž„εŒ–ε΅Œε₯—ζ ·εΌηš„ε†…εΉγ€‚
1794
1795ζ”―ζŒθ‡ͺεŠ¨ε€„η†ε­—η¬¦δΈ­ηš„εΌ•ε·γ€εζ–œζ η­‰η‰ΉζŠη¬¦ε·οΌŒζ— ιœ€ζ‰‹εŠ¨θ½¬δΉ‰οΌš
1796
1797```moonscript
1798str = |
1799 path: "C:\Program Files\App"
1800 note: 'He said: "#{Hello}!"'
1801```
1802<YueDisplay>
1803<pre>
1804str = |
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
1650sum = (x, y) -> return x + y 1914sum = (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
1869result, msg = do 2133result, 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
1874print result, msg 2138print result, msg
1875``` 2139```
1876<YueDisplay> 2140<YueDisplay>
1877<pre> 2141<pre>
1878result, msg = do 2142result, 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
1883print result, msg 2147print 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
@@ -2210,6 +2474,45 @@ slice = [item for item in *items[,,2]]
2210</pre> 2474</pre>
2211</YueDisplay> 2475</YueDisplay>
2212 2476
2477ζœ€ε°ε’Œζœ€ε€§θΎΉη•Œιƒ½ε―δ»₯ζ˜―θ΄Ÿζ•°οΌŒδ½Ώη”¨θ΄Ÿζ•°ζ„ε‘³η€θΎΉη•Œζ˜―δ»Žθ‘¨ηš„ζœ«ε°ΎεΌ€ε§‹θ‘η—ηš„γ€‚
2478
2479```moonscript
2480-- ε–ζœ€εŽ4δΈͺε…ƒη΄ 
2481slice = [item for item in *items[-4,-1]]
2482```
2483<YueDisplay>
2484<pre>
2485-- ε–ζœ€εŽ4δΈͺε…ƒη΄ 
2486slice = [item for item in *items[-4,-1]]
2487</pre>
2488</YueDisplay>
2489
2490εˆ‡η‰‡ηš„ζ­₯ι•ΏδΉŸε―δ»₯ζ˜―θ΄Ÿζ•°οΌŒθΏ™ζ„ε‘³η€ε…ƒη΄ δΌšδ»₯η›Έεηš„ι‘ΊεΊθ’«ε–ε‡Ίγ€‚
2491
2492```moonscript
2493reverse_slice = [item for item in *items[-1,1,-1]]
2494```
2495<YueDisplay>
2496<pre>
2497reverse_slice = [item for item in *items[-1,1,-1]]
2498</pre>
2499</YueDisplay>
2500
2501#### εˆ‡η‰‡θ‘¨θΎΎεΌ
2502
2503εˆ‡η‰‡δΉŸε―δ»₯作为葨达式ζ₯使用。可δ»₯η”¨δΊŽθŽ·ε–δΈ€δΈͺθ‘¨εŒ…ε«ηš„ε­εˆ—θ‘¨γ€‚
2504
2505```moonscript
2506-- 取第2ε’Œη¬¬4δΈͺε…ƒη΄ δ½œδΈΊζ–°ηš„εˆ—θ‘¨
2507sub_list = items[2, 4]
2508```
2509<YueDisplay>
2510<pre>
2511-- 取第2ε’Œη¬¬4δΈͺε…ƒη΄ δ½œδΈΊζ–°ηš„εˆ—θ‘¨
2512sub_list = items[2, 4]
2513</pre>
2514</YueDisplay>
2515
2213## for εΎͺ环 2516## for εΎͺ环
2214 2517
2215LuaδΈ­ζœ‰δΈ€η§forεΎͺηŽ―ε½’εΌοΌŒζ•°ε­—εž‹ε’Œι€šη”¨εž‹οΌš 2518LuaδΈ­ζœ‰δΈ€η§forεΎͺηŽ―ε½’εΌοΌŒζ•°ε­—εž‹ε’Œι€šη”¨εž‹οΌš
@@ -2286,9 +2589,24 @@ doubled_evens = for i = 1, 20
2286</pre> 2589</pre>
2287</YueDisplay> 2590</YueDisplay>
2288 2591
2289ζ‚¨θΏ˜ε―δ»₯η»“εˆforεΎͺ环葨达式与continueθ―­ε₯ζ₯过滀值。 2592ζ­€ε€–οΌŒforεΎͺηŽ―θΏ˜ζ”―ζŒεΈ¦θΏ”ε›žε€Όηš„breakθ―­ε₯οΌŒθΏ™ζ ·εΎͺ环本身就可δ»₯δ½œδΈΊδΈ€δΈͺθ‘¨θΎΎεΌοΌŒεœ¨ζ»‘θΆ³ζ‘δ»Άζ—Άζε‰ι€€ε‡ΊεΉΆθΏ”ε›žζœ‰ζ„δΉ‰ηš„η»“ζžœγ€‚
2290 2593
2291ζ³¨ζ„ε‡ΊηŽ°εœ¨ε‡½ζ•°δ½“ζœ«ε°Ύηš„forεΎͺηŽ―οΌŒδΈδΌšθ’«ε½“δ½œζ˜―δΈ€δΈͺθ‘¨θΎΎεΌοΌŒεΉΆε°†εΎͺηŽ―η»“ζžœη΄―η§―εˆ°δΈ€δΈͺεˆ—θ‘¨δΈ­δ½œδΈΊθΏ”ε›žε€ΌοΌˆη›ΈεοΌŒε‡½ζ•°ε°†θΏ”ε›žnilοΌ‰γ€‚ε¦‚ζžœθ¦ε‡½ζ•°ζœ«ε°Ύηš„εΎͺηŽ―θ½¬ζ’δΈΊεˆ—θ‘¨θ‘¨θΎΎεΌοΌŒε―δ»₯δ½Ώη”¨θΏ”ε›žθ―­ε₯加forεΎͺηŽ―θ‘¨θΎΎεΌγ€‚ 2594δΎ‹ε¦‚οΌŒζŸ₯找第一δΈͺ倧于10ηš„ζ•°ε­—οΌš
2595
2596```moonscript
2597first_large = for n in *numbers
2598 break n if n > 10
2599```
2600<YueDisplay>
2601<pre>
2602first_large = for n in *numbers
2603 break n if n > 10
2604</pre>
2605</YueDisplay>
2606
2607你还可δ»₯η»“εˆforεΎͺ环葨达式与continueθ―­ε₯ζ₯过滀值。
2608
2609ζ³¨ζ„ε‡ΊηŽ°εœ¨ε‡½ζ•°δ½“ζœ«ε°Ύηš„forεΎͺηŽ―οΌŒδΈδΌšθ’«ε½“δ½œζ˜―δΈ€δΈͺ葨达式幢将εΎͺηŽ―η»“ζžœη΄―η§―εˆ°δΈ€δΈͺεˆ—θ‘¨δΈ­δ½œδΈΊθΏ”ε›žε€ΌοΌˆη›ΈεοΌŒε‡½ζ•°ε°†θΏ”ε›žnilοΌ‰γ€‚ε¦‚ζžœθ¦ε‡½ζ•°ζœ«ε°Ύηš„εΎͺηŽ―θ½¬ζ’δΈΊεˆ—θ‘¨θ‘¨θΎΎεΌοΌŒε―δ»₯ζ˜ΎεΌεœ°δ½Ώη”¨θΏ”ε›žθ―­ε₯加forεΎͺηŽ―θ‘¨θΎΎεΌγ€‚
2292 2610
2293```moonscript 2611```moonscript
2294func_a = -> for i = 1, 10 do print i 2612func_a = -> for i = 1, 10 do print i
@@ -2513,7 +2831,7 @@ print "你真幸运!" unless math.random! > 0.1
2513 2831
2514### θŒƒε›΄θ‘¨θΎΎεΌ 2832### θŒƒε›΄θ‘¨θΎΎεΌ
2515 2833
2516您可δ»₯δ½Ώη”¨θŒƒε›΄θ‘¨θΎΎεΌζ₯ηΌ–ε†™θΏ›θ‘ŒθŒƒε›΄ζ£€ζŸ₯ηš„δ»£η γ€‚ 2834你可δ»₯δ½Ώη”¨θŒƒε›΄θ‘¨θΎΎεΌζ₯ηΌ–ε†™θΏ›θ‘ŒθŒƒε›΄ζ£€ζŸ₯ηš„δ»£η γ€‚
2517 2835
2518```moonscript 2836```moonscript
2519a = 5 2837a = 5
@@ -2586,28 +2904,26 @@ reader\parse_line! until reader\eof!
2586 2904
2587## switch θ―­ε₯ 2905## switch θ―­ε₯
2588 2906
2589switchθ―­ε₯ζ˜―δΈΊδΊ†η€εŒ–ζ£€ζŸ₯δΈ€η³»εˆ—η›ΈεŒε€Όηš„ifθ―­ε₯θ€ŒζδΎ›ηš„η€ε†™θ―­ζ³•γ€‚θ¦ζ³¨ζ„η”¨δΊŽζ―”θΎƒζ£€ζŸ₯ηš„η›ζ ‡ε€Όεͺ会θ‘η—δΈ€ζ¬‘γ€‚ε’Œifθ―­ε₯δΈ€ζ ·οΌŒswitchθ―­ε₯εœ¨ζœ€εŽε―δ»₯ζŽ₯δΈ€δΈͺelse代码块ζ₯ε€„η†ζ²‘ζœ‰εŒΉι…ηš„ζƒ…ε†΅γ€‚εœ¨η”Ÿζˆηš„Luaδ»£η δΈ­οΌŒθΏ›θ‘Œζ―”θΎƒζ˜―δ½Ώη”¨==ζ“δ½œη¬¦εŒζˆηš„。 2907switchθ―­ε₯ζ˜―δΈΊδΊ†η€εŒ–ζ£€ζŸ₯δΈ€η³»εˆ—η›ΈεŒε€Όηš„ifθ―­ε₯θ€ŒζδΎ›ηš„η€ε†™θ―­ζ³•γ€‚θ¦ζ³¨ζ„η”¨δΊŽζ―”θΎƒζ£€ζŸ₯ηš„η›ζ ‡ε€Όεͺ会θ‘η—δΈ€ζ¬‘γ€‚ε’Œifθ―­ε₯δΈ€ζ ·οΌŒswitchθ―­ε₯εœ¨ζœ€εŽε―δ»₯ζŽ₯δΈ€δΈͺelse代码块ζ₯ε€„η†ζ²‘ζœ‰εŒΉι…ηš„ζƒ…ε†΅γ€‚εœ¨η”Ÿζˆηš„Luaδ»£η δΈ­οΌŒθΏ›θ‘Œζ―”θΎƒζ˜―δ½Ώη”¨==ζ“δ½œη¬¦εŒζˆηš„。switchθ―­ε₯中也可δ»₯使用衋值葨达式ζ₯ε‚¨ε­˜δΈ΄ζ—Άε˜ι‡ε€Όγ€‚
2590 2908
2591```moonscript 2909```moonscript
2592name = "Dan" 2910switch name := "Dan"
2593switch name
2594 when "Robert" 2911 when "Robert"
2595 print "你是Robert" 2912 print "你是Robert"
2596 when "Dan", "Daniel" 2913 when "Dan", "Daniel"
2597 print "δ½ ηš„εε­—ζ˜―Dan" 2914 print "δ½ ηš„εε­—ζ˜―Dan"
2598 else 2915 else
2599 print "ζˆ‘δΈηŸ₯ι“δ½ ηš„εε­—" 2916 print "ζˆ‘δΈθ€θ―†δ½ οΌŒδ½ ηš„εε­—ζ˜―#{name}"
2600``` 2917```
2601<YueDisplay> 2918<YueDisplay>
2602<pre> 2919<pre>
2603name = "Dan" 2920switch name := "Dan"
2604switch name
2605 when "Robert" 2921 when "Robert"
2606 print "你是Robert" 2922 print "你是Robert"
2607 when "Dan", "Daniel" 2923 when "Dan", "Daniel"
2608 print "δ½ ηš„εε­—ζ˜―Dan" 2924 print "δ½ ηš„εε­—ζ˜―Dan"
2609 else 2925 else
2610 print "ζˆ‘δΈηŸ₯ι“δ½ ηš„εε­—" 2926 print "ζˆ‘δΈθ€θ―†δ½ οΌŒδ½ ηš„εε­—ζ˜―#{name}"
2611</pre> 2927</pre>
2612</YueDisplay> 2928</YueDisplay>
2613 2929
@@ -2684,7 +3000,7 @@ else
2684</pre> 3000</pre>
2685</YueDisplay> 3001</YueDisplay>
2686 3002
2687ε€ΌεΎ—ζ³¨ζ„ηš„ζ˜―οΌŒεœ¨η”ŸζˆLuaδ»£η ζ—ΆοΌŒζˆ‘δ»¬θ¦εšζ£€ζŸ₯ηš„η›ζ ‡ε˜ι‡δΌšζ”Ύεœ¨==θ‘¨θΎΎεΌηš„ε³δΎ§γ€‚ε½“ζ‚¨εΈŒζœ›η»™when子ε₯ηš„ζ―”θΎƒε―Ήθ±‘εšδΉ‰δΈ€δΈͺ\_\_eq元方法ζ₯ι‡θ½½εˆ€ζ–­ι€»θΎ‘ζ—ΆοΌŒε―θƒ½δΌšζœ‰η”¨γ€‚ 3003ε€ΌεΎ—ζ³¨ζ„ηš„ζ˜―οΌŒεœ¨η”ŸζˆLuaδ»£η ζ—ΆοΌŒζˆ‘δ»¬θ¦εšζ£€ζŸ₯ηš„η›ζ ‡ε˜ι‡δΌšζ”Ύεœ¨==θ‘¨θΎΎεΌηš„ε³δΎ§γ€‚ε½“δ½ εΈŒζœ›η»™when子ε₯ηš„ζ―”θΎƒε―Ήθ±‘εšδΉ‰δΈ€δΈͺ\_\_eq元方法ζ₯ι‡θ½½εˆ€ζ–­ι€»θΎ‘ζ—ΆοΌŒε―θƒ½δΌšζœ‰η”¨γ€‚
2688 3004
2689### θ‘¨ζ ΌεŒΉι… 3005### θ‘¨ζ ΌεŒΉι…
2690 3006
@@ -2744,9 +3060,126 @@ switch item
2744</pre> 3060</pre>
2745</YueDisplay> 3061</YueDisplay>
2746 3062
3063你也可δ»₯εŒΉι…ζ•°η»„ε…ƒη΄ γ€θ‘¨ζ Όε­—ζ΅οΌŒη”šθ‡³δ½Ώη”¨ζ•°η»„ζˆ–θ‘¨ζ Όε­—ι’量ζ₯εŒΉι…ε΅Œε₯—ηš„η»“ζž„γ€‚
3064
3065εŒΉι…ζ•°η»„ε…ƒη΄ γ€‚
3066
3067```moonscript
3068switch 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>
3078switch 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
3091switch 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>
3101switch 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
3114switch 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>
3124switch 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
3137switch 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>
3148switch 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
3162segments = ["admin", "users", "logs", "view"]
3163switch 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>
3171segments = ["admin", "users", "logs", "view"]
3172switch 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
2747## 青向对豑编程 3180## 青向对豑编程
2748 3181
2749在δ»₯δΈ‹ηš„η€ΊδΎ‹δΈ­οΌŒζœˆδΉ‹θ„šζœ¬η”Ÿζˆηš„Luaδ»£η ε―θƒ½ηœ‹θ΅·ζ₯δΌšεΎˆε€ζ‚γ€‚ζ‰€δ»₯ζœ€ε₯½δΈ»θ¦ε…³ζ³¨ζœˆδΉ‹θ„šζœ¬δ»£η ε±‚ι’ηš„ζ„δΉ‰οΌŒη„ΆεŽε¦‚ζžœζ‚¨ζƒ³ηŸ₯ι“ε…³δΊŽι’ε‘ε―Ήθ±‘εŠŸθƒ½ηš„εžηŽ°η»†θŠ‚οΌŒε†ζŸ₯ηœ‹Lua代码。 3182在δ»₯δΈ‹ηš„η€ΊδΎ‹δΈ­οΌŒζœˆδΉ‹θ„šζœ¬η”Ÿζˆηš„Luaδ»£η ε―θƒ½ηœ‹θ΅·ζ₯δΌšεΎˆε€ζ‚γ€‚ζ‰€δ»₯ζœ€ε₯½δΈ»θ¦ε…³ζ³¨ζœˆδΉ‹θ„šζœ¬δ»£η ε±‚ι’ηš„ζ„δΉ‰οΌŒη„ΆεŽε¦‚ζžœδ½ ζƒ³ηŸ₯ι“ε…³δΊŽι’ε‘ε―Ήθ±‘εŠŸθƒ½ηš„εžηŽ°η»†θŠ‚οΌŒε†ζŸ₯ηœ‹Lua代码。
2750 3183
2751δΈ€δΈͺη€ε•ηš„η±»οΌš 3184δΈ€δΈͺη€ε•ηš„η±»οΌš
2752 3185
@@ -3214,7 +3647,7 @@ x = class
3214 3647
3215### 类混合 3648### 类混合
3216 3649
3217您可δ»₯ι€šθΏ‡δ½Ώη”¨ `using` ε…³ι”ε­—ζ₯εžηŽ°η±»ζ··εˆγ€‚θΏ™ζ„ε‘³η€ζ‚¨ε―δ»₯δ»ŽδΈ€δΈͺζ™ι€š Lua θ‘¨ζ Όζˆ–ε·²εšδΉ‰ηš„η±»ε―Ήθ±‘δΈ­οΌŒε€εˆΆε‡½ζ•°εˆ°ζ‚¨εˆ›ε»Ίηš„ζ–°η±»δΈ­γ€‚ε½“ζ‚¨δ½Ώη”¨ζ™ι€š Lua θ‘¨ζ ΌθΏ›θ‘Œη±»ζ··εˆζ—ΆοΌŒζ‚¨ζœ‰ζœΊδΌšη”¨θ‡ͺε·±ηš„εžηްζ₯ι‡ε†™η±»ηš„η΄’εΌ•ζ–Ήζ³•οΌˆδΎ‹ε¦‚ε…ƒζ–Ήζ³• `__index`οΌ‰γ€‚η„Άθ€ŒοΌŒε½“ζ‚¨δ»ŽδΈ€δΈͺη±»ε―Ήθ±‘εšζ··εˆζ—ΆοΌŒιœ€θ¦ζ³¨ζ„ηš„ζ˜―θ―₯η±»ε―Ήθ±‘ηš„ε…ƒζ–Ήζ³•ε°†δΈδΌšθ’«ε€εˆΆεˆ°ζ–°η±»γ€‚ 3650你可δ»₯ι€šθΏ‡δ½Ώη”¨ `using` ε…³ι”ε­—ζ₯εžηŽ°η±»ζ··εˆγ€‚θΏ™ζ„ε‘³η€δ½ ε―δ»₯δ»ŽδΈ€δΈͺζ™ι€š Lua θ‘¨ζ Όζˆ–ε·²εšδΉ‰ηš„η±»ε―Ήθ±‘δΈ­οΌŒε€εˆΆε‡½ζ•°εˆ°δ½ εˆ›ε»Ίηš„ζ–°η±»δΈ­γ€‚ε½“δ½ δ½Ώη”¨ζ™ι€š Lua θ‘¨ζ ΌθΏ›θ‘Œη±»ζ··εˆζ—ΆοΌŒδ½ ζœ‰ζœΊδΌšη”¨θ‡ͺε·±ηš„εžηްζ₯ι‡ε†™η±»ηš„η΄’εΌ•ζ–Ήζ³•οΌˆδΎ‹ε¦‚ε…ƒζ–Ήζ³• `__index`οΌ‰γ€‚η„Άθ€ŒοΌŒε½“δ½ δ»ŽδΈ€δΈͺη±»ε―Ήθ±‘εšζ··εˆζ—ΆοΌŒιœ€θ¦ζ³¨ζ„ηš„ζ˜―θ―₯η±»ε―Ήθ±‘ηš„ε…ƒζ–Ήζ³•ε°†δΈδΌšθ’«ε€εˆΆεˆ°ζ–°η±»γ€‚
3218 3651
3219```moonscript 3652```moonscript
3220MyIndex = __index: var: 1 3653MyIndex = __index: var: 1
@@ -3316,22 +3749,22 @@ me = create_person "Leaf", [dad, mother, sister]
3316 3749
3317εœ¨ζ­€η”¨ζ³•δΈ­οΌŒwith可δ»₯蒫视为Kη»„εˆε­οΌˆk-combinatorοΌ‰ηš„δΈ€η§η‰ΉζŠε½’式。 3750εœ¨ζ­€η”¨ζ³•δΈ­οΌŒwith可δ»₯蒫视为Kη»„εˆε­οΌˆk-combinatorοΌ‰ηš„δΈ€η§η‰ΉζŠε½’式。
3318 3751
3319ε¦‚ζžœζ‚¨ζƒ³η»™θ‘¨θΎΎεΌε¦ε€–θ΅·δΈ€δΈͺεη§°ηš„θ―οΌŒwithθ―­ε₯δΈ­ηš„θ‘¨θΎΎεΌδΉŸε―δ»₯ζ˜―δΈ€δΈͺθ΅‹ε€Όθ―­ε₯。 3752ε¦‚ζžœδ½ ζƒ³η»™θ‘¨θΎΎεΌε¦ε€–θ΅·δΈ€δΈͺεη§°ηš„θ―οΌŒwithθ―­ε₯δΈ­ηš„θ‘¨θΎΎεΌδΉŸε―δ»₯ζ˜―δΈ€δΈͺθ΅‹ε€Όθ―­ε₯。
3320 3753
3321```moonscript 3754```moonscript
3322with str = "δ½ ε₯½" 3755with str := "δ½ ε₯½"
3323 print "εŽŸε§‹:", str 3756 print "εŽŸε§‹:", str
3324 print "倧写:", \upper! 3757 print "倧写:", \upper!
3325``` 3758```
3326<YueDisplay> 3759<YueDisplay>
3327<pre> 3760<pre>
3328with str = "δ½ ε₯½" 3761with str := "δ½ ε₯½"
3329 print "εŽŸε§‹:", str 3762 print "εŽŸε§‹:", str
3330 print "倧写:", \upper! 3763 print "倧写:", \upper!
3331</pre> 3764</pre>
3332</YueDisplay> 3765</YueDisplay>
3333 3766
3334在withθ―­ε₯中可δ»₯使用`[]`θΏι—η‰ΉζŠι”。 3767你可δ»₯在 `with` θ―­ε₯中使用 `[]` θΏι—η‰ΉζŠι”。
3335 3768
3336```moonscript 3769```moonscript
3337with tb 3770with tb
@@ -3354,6 +3787,19 @@ with tb
3354</pre> 3787</pre>
3355</YueDisplay> 3788</YueDisplay>
3356 3789
3790`with?` 是 `with` θ―­ζ³•ηš„δΈ€δΈͺε’žεΌΊη‰ˆζœ¬οΌŒεΌ•ε…₯δΊ†ε­˜εœ¨ζ€§ζ£€ζŸ₯οΌŒη”¨δΊŽεœ¨δΈζ˜ΎεΌεˆ€η©Ίηš„ζƒ…ε†΅δΈ‹ε‰ε…¨θΏι—可能为 nil ηš„ε―Ήθ±‘γ€‚
3791
3792```moonscript
3793with? obj
3794 print obj.name
3795```
3796<YueDisplay>
3797<pre>
3798with? obj
3799 print obj.name
3800</pre>
3801</YueDisplay>
3802
3357## do θ―­ε₯ 3803## do θ―­ε₯
3358 3804
3359ε½“η”¨δ½œθ―­ε₯ζ—ΆοΌŒdoθ―­ε₯ηš„δ½œη”¨ε°±εƒεœ¨LuaδΈ­ε·δΈε€šγ€‚ 3805ε½“η”¨δ½œθ―­ε₯ζ—ΆοΌŒdoθ―­ε₯ηš„δ½œη”¨ε°±εƒεœ¨LuaδΈ­ε·δΈε€šγ€‚
@@ -3373,7 +3819,7 @@ print var -- θΏ™ι‡Œζ˜―nil
3373</pre> 3819</pre>
3374</YueDisplay> 3820</YueDisplay>
3375 3821
3376ζœˆδΉ‹θ„šζœ¬ηš„ **do** 也可δ»₯η”¨δ½œθ‘¨θΎΎεΌγ€‚ε…θΈζ‚¨ε°†ε€šθ‘Œδ»£η ηš„ε€„η†εˆεΉΆδΈΊδΈ€δΈͺθ‘¨θΎΎεΌοΌŒεΉΆε°†doθ―­ε₯δ»£η ε—ηš„ζœ€εŽδΈ€δΈͺθ―­ε₯δ½œδΈΊθ‘¨θΎΎεΌθΏ”ε›žηš„η»“ζžœγ€‚ 3822ζœˆδΉ‹θ„šζœ¬ηš„ **do** 也可δ»₯η”¨δ½œθ‘¨θΎΎεΌγ€‚ε…θΈδ½ ε°†ε€šθ‘Œδ»£η ηš„ε€„η†εˆεΉΆδΈΊδΈ€δΈͺθ‘¨θΎΎεΌοΌŒεΉΆε°†doθ―­ε₯δ»£η ε—ηš„ζœ€εŽδΈ€δΈͺθ―­ε₯δ½œδΈΊθ‘¨θΎΎεΌθΏ”ε›žηš„η»“ζžœγ€‚
3377 3823
3378```moonscript 3824```moonscript
3379counter = do 3825counter = do
@@ -4332,8 +4778,8 @@ simplified: boolean
4332 4778
4333η‰ˆζƒ (c) 2017-2025 ζŽη‘Ύ \<dragon-fly@qq.com\> 4779η‰ˆζƒ (c) 2017-2025 ζŽη‘Ύ \<dragon-fly@qq.com\>
4334 4780
4335η‰Ήζ­€ε…θ΄ΉζŽˆδΊˆδ»»δ½•θŽ·εΎ—ζœ¬θ½―δ»Άε‰―ζœ¬ε’Œη›Έε…³ζ–‡ζ‘£ζ–‡δ»ΆοΌˆδΈ‹η§°β€œθ½―δ»Άβ€οΌ‰ηš„δΊΊδΈε—ι™εˆΆεœ°ε€„η½θ―₯θ½―δ»Άηš„ζƒεˆ©οΌŒεŒ…ζ‹¬δΈε—ι™εˆΆεœ°δ½Ώη”¨γ€ε€εˆΆγ€δΏζ”Ήγ€εˆεΉΆγ€ε‘εΈƒγ€εˆ†ε‘γ€θ½¬ζŽˆθΈε―ε’Œ/ζˆ–ε‡Ίε”θ―₯θ½―δ»Άε‰―ζœ¬οΌŒδ»₯εŠε†ζŽˆζƒθ’«ι…ε‘δΊ†ζœ¬θ½―δ»Άηš„δΊΊε¦‚δΈŠηš„ζƒεˆ©οΌŒι‘»εœ¨δΈ‹εˆ—ζ‘δ»ΆδΈ‹οΌš 4781η‰Ήζ­€ε…θ΄ΉζŽˆδΊˆδ»»δ½•θŽ·εΎ—ζœ¬θ½―δ»Άε‰―ζœ¬ε’Œη›Έε…³ζ–‡ζ‘£ζ–‡δ»ΆοΌˆδΈ‹η§°β€œθ½―δ»Άβ€οΌ‰ηš„δΊΊδΈε—ι™εˆΆεœ°ε€„η½θ―₯θ½―δ»Άηš„ζƒεˆ©οΌŒεŒ…ζ‹¬δΈε—ι™εˆΆεœ°δ½Ώη”¨γ€ε€εˆΆγ€δΏζ”Ήγ€εˆεΉΆγ€ε‘εΈƒγ€εˆ†ε‘γ€θ½¬ζŽˆθΈε―ε’Œ/ζˆ–ε‡Ίε”θ―₯θ½―δ»Άε‰―ζœ¬οΌŒδ»₯εŠε†ζŽˆζƒθ’«ι…ε‘δΊ†ζœ¬θ½―δ»Άηš„δΊΊε¦‚δΈŠηš„ζƒεˆ©οΌŒι‘»εœ¨δΈ‹εˆ—ζ‘δ»ΆδΈ‹οΌš
4336δΈŠθΏ°η‰ˆζƒε£°ζ˜Žε’Œζœ¬θΈε―ε£°ζ˜ŽεΊ”εŒ…ε«εœ¨θ―₯θ½―δ»Άηš„ζ‰€ζœ‰ε‰―ζœ¬ζˆ–εžθ΄¨ζˆεˆ†δΈ­γ€‚ 4782δΈŠθΏ°η‰ˆζƒε£°ζ˜Žε’Œζœ¬θΈε―ε£°ζ˜ŽεΊ”εŒ…ε«εœ¨θ―₯θ½―δ»Άηš„ζ‰€ζœ‰ε‰―ζœ¬ζˆ–εžθ΄¨ζˆεˆ†δΈ­γ€‚
4337ζœ¬θ½―δ»Άζ˜―β€œε¦‚ζ­€β€ζδΎ›ηš„οΌŒζ²‘ζœ‰δ»»δ½•ε½’εΌηš„ζ˜Žη€Ίζˆ–ζš—η€Ίηš„δΏθ―οΌŒεŒ…ζ‹¬δ½†δΈι™δΊŽε―Ήι€‚ι”€ζ€§γ€η‰Ήεšη”¨ι€”ηš„ι€‚η”¨ζ€§ε’ŒδΈδΎ΅ζƒηš„δΏθ―γ€‚εœ¨δ»»δ½•ζƒ…ε†΅δΈ‹οΌŒδ½œθ€…ζˆ–η‰ˆζƒζŒζœ‰δΊΊιƒ½δΈε―Ήδ»»δ½•η΄’θ΅”γ€ζŸε³ζˆ–ε…Άδ»–θ΄£δ»»θ΄Ÿθ΄£οΌŒζ— θΊθΏ™δΊ›θΏ½θ΄£ζ₯θ‡ͺεˆεŒγ€δΎ΅ζƒζˆ–ε…Άεƒθ‘ŒδΈΊδΈ­οΌŒθΏ˜ζ˜―δΊ§η”ŸδΊŽγ€ζΊδΊŽζˆ–ζœ‰ε…³δΊŽζœ¬θ½―δ»Άδ»₯εŠζœ¬θ½―δ»Άηš„δ½Ώη”¨ζˆ–ε…Άεƒε€„η½γ€‚ 4783ζœ¬θ½―δ»Άζ˜―β€œε¦‚ζ­€β€ζδΎ›ηš„οΌŒζ²‘ζœ‰δ»»δ½•ε½’εΌηš„ζ˜Žη€Ίζˆ–ζš—η€Ίηš„δΏθ―οΌŒεŒ…ζ‹¬δ½†δΈι™δΊŽε―Ήι€‚ι”€ζ€§γ€η‰Ήεšη”¨ι€”ηš„ι€‚η”¨ζ€§ε’ŒδΈδΎ΅ζƒηš„δΏθ―γ€‚εœ¨δ»»δ½•ζƒ…ε†΅δΈ‹οΌŒδ½œθ€…ζˆ–η‰ˆζƒζŒζœ‰δΊΊιƒ½δΈε―Ήδ»»δ½•η΄’θ΅”γ€ζŸε³ζˆ–ε…Άδ»–θ΄£δ»»θ΄Ÿθ΄£οΌŒζ— θΊθΏ™δΊ›θΏ½θ΄£ζ₯θ‡ͺεˆεŒγ€δΎ΅ζƒζˆ–ε…Άεƒθ‘ŒδΈΊδΈ­οΌŒθΏ˜ζ˜―δΊ§η”ŸδΊŽγ€ζΊδΊŽζˆ–ζœ‰ε…³δΊŽζœ¬θ½―δ»Άδ»₯εŠζœ¬θ½―δ»Άηš„δ½Ώη”¨ζˆ–ε…Άεƒε€„η½γ€‚
4338 4784
4339<CompilerModal /> 4785<CompilerModal />
diff --git a/makefile b/makefile
index d1b074a..d7e85d3 100644
--- a/makefile
+++ b/makefile
@@ -391,7 +391,6 @@ test: debug
391 @./$(BIN_NAME) $(TEST_INPUT)/try_catch.yue -o $(TEST_OUTPUT)/5.1/try_catch.lua --target=5.1 391 @./$(BIN_NAME) $(TEST_INPUT)/try_catch.yue -o $(TEST_OUTPUT)/5.1/try_catch.lua --target=5.1
392 @./$(BIN_NAME) $(TEST_INPUT)/attrib.yue -o $(TEST_OUTPUT)/5.1/attrib.lua --target=5.1 392 @./$(BIN_NAME) $(TEST_INPUT)/attrib.yue -o $(TEST_OUTPUT)/5.1/attrib.lua --target=5.1
393 @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(TEST_OUTPUT)/5.1/test/loops_spec.lua --target=5.1 393 @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(TEST_OUTPUT)/5.1/test/loops_spec.lua --target=5.1
394 @./$(BIN_NAME) $(TEST_INPUT)/literals.yue -o $(TEST_OUTPUT)/5.1/literals.lua --target=5.1
395 @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(TEST_OUTPUT) 394 @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(TEST_OUTPUT)
396 @echo -en "Compile time: " 395 @echo -en "Compile time: "
397 @$(END_TIME) 396 @$(END_TIME)
@@ -410,7 +409,6 @@ gen: release
410 @./$(BIN_NAME) $(TEST_INPUT)/loops.yue -o $(GEN_OUTPUT)/5.1/loops.lua --target=5.1 409 @./$(BIN_NAME) $(TEST_INPUT)/loops.yue -o $(GEN_OUTPUT)/5.1/loops.lua --target=5.1
411 @./$(BIN_NAME) $(TEST_INPUT)/try_catch.yue -o $(GEN_OUTPUT)/5.1/try_catch.lua --target=5.1 410 @./$(BIN_NAME) $(TEST_INPUT)/try_catch.yue -o $(GEN_OUTPUT)/5.1/try_catch.lua --target=5.1
412 @./$(BIN_NAME) $(TEST_INPUT)/attrib.yue -o $(GEN_OUTPUT)/5.1/attrib.lua --target=5.1 411 @./$(BIN_NAME) $(TEST_INPUT)/attrib.yue -o $(GEN_OUTPUT)/5.1/attrib.lua --target=5.1
413 @./$(BIN_NAME) $(TEST_INPUT)/literals.yue -o $(GEN_OUTPUT)/5.1/literals.lua --target=5.1
414 @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(GEN_OUTPUT)/5.1/test/loops_spec.lua --target=5.1 412 @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(GEN_OUTPUT)/5.1/test/loops_spec.lua --target=5.1
415 @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(GEN_OUTPUT) 413 @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(GEN_OUTPUT)
416 @echo -en "Compile time: " 414 @echo -en "Compile time: "
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
15do 15do
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
96do 96do
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
244do
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
251do
252 setupMeeting = (participants) ->
253 [chair, ..._, secretary] = participants
254 print chair, secretary
255
256 setupMeeting ["Alice", "Bob", "Charlie", "David"]
257 -- Output: Alice David
258
259do
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
271do
272 [
273 _
274 ...middle
275 _
276 ] = tb
277
278do
279 {a, :abc, b, :def, ...sub, d, e} = tb
280
243nil 281nil
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
85do
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
142do
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
90do
91 transactions = ["T001", "T002", "T003", "T004", "T005"]
92 middleTransactions = transactions[2, -2]
93 print middleTransactions -- => {"T002", "T003", "T004"}
94
95do
96 logs =
97 - start: 0, end: 100
98 - start: 100, end: 200
99 - start: 200, end: 123
100 print logs[#].end -- => 123
101
102do
103 pendingOrders = ["O001", "O002", "O003", "O004"]
104 print pendingOrders[# - 1] -- => "O003"
105
106do
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
117do
118 cloneList1 = (list) -> list[,]
119 cloneList2 = (list) -> [...list,]
120 cloneTable = (tb) -> {...tb}
121
122do
123 print(
124 globalTB[#]
125 a.b.c[# - 2]
126 x?\y?!.z?[# - 3]
127 )
128
129do
130 f = ->
131 print(
132 globalTB[#]\end 123
133 a.b.c[5,-5][# - 2]
134 x?\y?!.z?[# - 3]?[, -3]
135 )
136
90nil 137nil
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
213do 213do
214 until x := func 'a', b do 214 until x := func 'a', b do
215 print "false expected" 215 print "false expected"
216
217do
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
254do
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
61print $NumAndStr 123, 'xyz' 61print $NumAndStr 123, 'xyz'
62 62
63macro NumAndStr2 = (num`Num, str`SingleString) -> |
64 [#{num}, #{str}]
65
66print $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
102macro reduce = (items, def, action)-> 107macro reduce = (items, def, action)->
103 $showMacro "reduce", "if ##{items} == 0 108 $showMacro "reduce", |
104 #{def} 109 if ##{items} == 0
105else 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
111macro foreach = (items, action)-> 117macro foreach = (items, action)->
112 $showMacro "foreach", "for _ in *#{items} 118 $showMacro "foreach", "for _ in *#{items}
@@ -154,13 +160,15 @@ macro curry = (...)->
154f = $curry x,y,z,do 160f = $curry x,y,z,do
155 print x,y,z 161 print x,y,z
156 162
157macro get_inner = (var)-> "do 163macro get_inner = (var)-> |
158 a = 1 164 do
159 a + 1" 165 a = 1
166 a + 1
160 167
161macro get_inner_hygienic = (var)-> "(-> 168macro get_inner_hygienic = (var)-> |
162 local a = 1 169 (->
163 a + 1)!" 170 local a = 1
171 a + 1)!
164 172
165do 173do
166 a = 8 174 a = 8
@@ -196,6 +204,18 @@ end
196 204
197print x 205print x
198 206
207import "yue"
208macro 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
199macro def = (fname, ...)-> 219macro 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
320macro tb = -> "{'abc', a:123, <call>:=> 998}" 340macro tb = -> |
341 {
342 'abc'
343 a: 123
344 <call>: => 998
345 }
346
321print $tb[1], $tb.a, ($tb)!, $tb! 347print $tb[1], $tb.a, ($tb)!, $tb!
322 348
323print "current line: #{ $LINE }" 349print "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
10export macro showMacro = (name, res)-> 10export macro showMacro = (name, res)->
11 if debugMacro then " 11 if debugMacro then |
12do 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(
39do 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
47export macro enum = (...) -> 48export 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
7macro to_lua = (code)-> 7macro 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
10macro trim = (name)-> 12macro trim = (name)-> |
11 "if result := #{name}\\match '[\\'\"](.*)[\\'\"]' then result else #{name}" 13 if result := #{name}\match '[\'"](.*)[\'"]'
14 result
15 else
16 #{name}
12 17
13export macro local = (decl, value = nil)-> 18export 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
8export macro todo = (msg)-> 8export 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 @@
1class 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
49class A extends Props
50 @prop 'x'
51 get: => @_x + 1000
52 set: (v) => @_x = v
53 new: =>
54 @_x = 0
55
56class B extends A
57 @prop 'abc', get: => "hello"
58
59b = B!
60b.x = 999
61print 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"
74something"hello"\world! 74something"hello"\world!
75something "hello"\world! 75something "hello"\world!
76 76
77do
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 ) |> print
145
146export 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
168nil
169 168
169do
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
178do
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
187do
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
196do
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
223do
224 switch v := "hello"
225 when "hello"
226 print "matched hello"
227 else
228 print "not matched"
229 -- output: matched hello
230
231do
232 f = -> "ok"
233 switch val := f!
234 when "ok"
235 print "it's ok"
236 -- output: it's ok
237
238
239do
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
250do
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
264do
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
275do
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
283do
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
292nil
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
264newline2"
265
248tb = {...other} 266tb = {...other}
249 267
250tbMix = { 268tbMix = {
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
95do
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
187nil
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
86do 86do
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 "
38do 38do
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
70do 70do
71 with ε˜ι‡k = "δΉ”" 71 with ε˜ι‡k := "δΉ”"
72 打印 \倧写! 72 打印 \倧写!
73 73
74do 74do
75 with ε˜ι‡a,ε˜ι‡b,ε˜ι‡c = "", "", "" 75 with ε˜ι‡a,ε˜ι‡b,ε˜ι‡c := "", "", ""
76 打印 \倧写! 76 打印 \倧写!
77 77
78do 78do
79 ε˜ι‡a = "εΊŠι“Ί" 79 ε˜ι‡a = "εΊŠι“Ί"
80 with ε˜ι‡a,ε˜ι‡b,ε˜ι‡c = "", "", "" 80 with ε˜ι‡a,ε˜ι‡b,ε˜ι‡c := "", "", ""
81 打印 \倧写! 81 打印 \倧写!
82 82
83do 83do
@@ -85,7 +85,7 @@ do
85 打印 \倧写! 85 打印 \倧写!
86 86
87do 87do
88 with ε˜ι‡k.ε˜ι‡j = "δΉ”" 88 with ε˜ι‡k.ε˜ι‡j := "δΉ”"
89 打印 \倧写! 89 打印 \倧写!
90 90
91do 91do
@@ -96,7 +96,7 @@ do
96 96
97do 97do
98 with ε˜ι‡a 98 with ε˜ι‡a
99 with .b = 2 99 with .b := 2
100 打印 .c 100 打印 .c
101 101
102do 102do
@@ -131,12 +131,12 @@ do
131 131
132do 132do
133 global 掩码 133 global 掩码
134 with? 掩码 = εžεΏƒηŸ©ε½’ ε½: w, 高: h, ι’œθ‰²: 0x66000000 134 with? 掩码 := εžεΏƒηŸ©ε½’ ε½: w, 高: h, ι’œθ‰²: 0x66000000
135 .触摸启用 = true 135 .触摸启用 = true
136 .εžε™¬θ§¦ζ‘Έ = true 136 .εžε™¬θ§¦ζ‘Έ = true
137 137
138do 138do
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
75do 75do
76 with k = "jo" 76 with k := "jo"
77 print \upper! 77 print \upper!
78 78
79do 79do
80 with a,b,c = "", "", "" 80 with a,b,c := "", "", ""
81 print \upper! 81 print \upper!
82 82
83do 83do
84 a = "bunk" 84 a = "bunk"
85 with a,b,c = "", "", "" 85 with a,b,c := "", "", ""
86 print \upper! 86 print \upper!
87 87
88do 88do
@@ -90,7 +90,7 @@ do
90 print \upper! 90 print \upper!
91 91
92do 92do
93 with k.j = "jo" 93 with k.j := "jo"
94 print \upper! 94 print \upper!
95 95
96do 96do
@@ -103,7 +103,7 @@ do
103do 103do
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
109do 109do
@@ -138,12 +138,12 @@ do
138 138
139do 139do
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
145do 145do
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
155do
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
168do
169 a = for i = 1, 100
170 with? x := tb[i]
171 break x if .id := 1
172
155nil 173nil
diff --git a/spec/outputs/5.1/literals.lua b/spec/outputs/5.1/literals.lua
deleted file mode 100644
index 36c705a..0000000
--- a/spec/outputs/5.1/literals.lua
+++ /dev/null
@@ -1,44 +0,0 @@
1local _ = {
2 121,
3 121.2323,
4 121.2323e-1,
5 121.2323e13434,
6 2323E34,
7 0x12323,
8 0xfF2323,
9 0xabcdef,
10 0xABCDEF,
11 0XFBC400,
12 2.7365508487142853e-35,
13 0xABCP321,
14 2.4074124304840448e-35,
15 6.4326233113470805e-94,
16 0.1171875,
17 162.1875,
18 3.1415926535897931,
19 1,
20 8,
21 15,
22 201,
23 .2323,
24 .2323e-1,
25 .2323e13434,
26 1LL,
27 1ULL,
28 9332LL,
29 9332,
30 0x2aLL,
31 0x2aULL,
32 1000000.0000001,
33 1234e5678,
34 1234E-5678,
35 0xDEADBEEF,
36 [[ hello world ]],
37 [=[ hello world ]=],
38 [====[ hello world ]====],
39 "another world",
40 'what world',
41 "\n hello world\n ",
42 'yeah\n what is going on\n here is something cool'
43}
44return 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
67end 67end
@@ -132,13 +132,11 @@ do
132end 132end
133do 133do
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
144end 142end
@@ -489,3 +487,131 @@ do
489 end 487 end
490 until false 488 until false
491end 489end
490local _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
499end
500do
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
589end
590do
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
617end
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
22local _anon_func_7 = function(a, b, c, tb) 22local _anon_func_7 = function(a, b, c, tb)
23 return tb.f(a, b, c) 23 return tb.f(a, b, c)
24end 24end
25local _anon_func_8 = function(_arg_0, ...)
26 local ok = _arg_0
27 return ...
28end
29local _anon_func_10 = function(_arg_0, ...)
30 local _ok_0 = _arg_0
31 if _ok_0 then
32 return ...
33 end
34end
35local _anon_func_9 = function(func, pcall)
36 return _anon_func_10(pcall(func))
37end
38local _anon_func_12 = function(_arg_0, ...)
39 local _ok_0 = _arg_0
40 if _ok_0 then
41 return ...
42 end
43end
44local _anon_func_11 = function(func, pcall)
45 return _anon_func_12(pcall(func))
46end
47local _anon_func_14 = function(_arg_0, ...)
48 local _ok_0 = _arg_0
49 if _ok_0 then
50 return ...
51 end
52end
53local _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))
61end
25local f 62local f
26f = function() 63f = 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
113end 193end
194local _anon_func_15 = function(a, b, c, tb)
195 return tb.f(a, b, c)
196end
197local _anon_func_16 = function(_arg_0, ...)
198 local ok = _arg_0
199 return ...
200end
201do
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
375end
376return 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
44end 44end
45local _anon_func_0 = function(print) 45local _anon_func_0 = function(print)
46 do 46 print(123)
47 print(123) 47 return { }
48 return { }
49 end
50end 48end
51return _(function() 49return _(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 f6d5d61..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}
23local map
24map = 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
33end
34local filter
35filter = 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
46end
47local reduce
48reduce = 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
54end
23print(reduce(filter(map({ 55print(reduce(filter(map({
24 1, 56 1,
25 2, 57 2,
@@ -77,6 +109,12 @@ end
77print("yuescript") 109print("yuescript")
78print(3) 110print(3)
79print("Valid enum type:", "Static") 111print("Valid enum type:", "Static")
112do
113 print(123, "hello")
114end
115do
116 print(123, "hello")
117end
80if tb ~= nil then 118if tb ~= nil then
81 tb:func() 119 tb:func()
82end 120end
@@ -177,6 +215,16 @@ for _key_0, _value_0 in pairs(b) do
177 end 215 end
178end 216end
179merge = _tab_0 217merge = _tab_0
218local last
219do
220 local _item_0 = data.items
221 last = _item_0[#_item_0]
222end
223local second_last
224do
225 local _item_0 = data.items
226 second_last = _item_0[#_item_0 - 1]
227end
180local mt = { } 228local mt = { }
181local add 229local add
182add = function(self, right) 230add = function(self, right)
@@ -307,6 +355,14 @@ func({
307 2, 355 2,
308 3 356 3
309}) 357})
358local f
359f = function()
360 return {
361 1,
362 2,
363 3
364 }
365end
310local tb = { 366local tb = {
311 name = "abc", 367 name = "abc",
312 values = { 368 values = {
@@ -547,6 +603,59 @@ end
547local two, four 603local two, four
548local _obj_0 = items 604local _obj_0 = items
549two, four = _obj_0[2], _obj_0[4] 605two, four = _obj_0[2], _obj_0[4]
606local orders = {
607 "first",
608 "second",
609 "third",
610 "fourth",
611 "last"
612}
613local 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
623end)(), orders[#orders]
624print(first)
625print(bulk)
626print(last)
627local first, rest
628do
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)()
641end
642local start, last
643do
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]
656end
657local _obj_0 = orders
658first, last = _obj_0[1], _obj_0[#_obj_0]
550local tuples = { 659local tuples = {
551 { 660 {
552 "hello", 661 "hello",
@@ -648,6 +757,56 @@ end)
648if success then 757if success then
649 print(result) 758 print(result)
650end 759end
760local a, b, c
761do
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
768end
769do
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
785end
786f((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))
795end)())
796f((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))
809end)())
651local a <const> = 123 810local a <const> = 123
652local _ <close> = setmetatable({ }, { 811local _ <close> = setmetatable({ }, {
653 __close = function() 812 __close = function()
@@ -657,10 +816,19 @@ local _ <close> = setmetatable({ }, {
657local a, b, c, d 816local a, b, c, d
658local _obj_0 = tb 817local _obj_0 = tb
659a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] 818a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
819Constant = 123
660local some_string = "Here is a string\n that has a line break in it." 820local some_string = "Here is a string\n that has a line break in it."
661print("I am " .. tostring(math.random() * 100) .. "% sure.") 821print("I am " .. tostring(math.random() * 100) .. "% sure.")
662local integer = 1000000 822local integer = 1000000
663local hex = 0xEFBBBF 823local hex = 0xEFBBBF
824local binary = 19
825local str = "key: value\nlist:\n - item1\n - " .. tostring(expr)
826local fn
827fn = function()
828 local str = "foo:\n bar: baz"
829 return str
830end
831local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
664local my_function 832local my_function
665my_function = function() end 833my_function = function() end
666my_function() 834my_function()
@@ -970,8 +1138,7 @@ local slice
970local _accum_0 = { } 1138local _accum_0 = { }
971local _len_0 = 1 1139local _len_0 = 1
972local _list_0 = items 1140local _list_0 = items
973local _max_0 = 5 1141for _index_0 = 1, 5 do
974for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do
975 local item = _list_0[_index_0] 1142 local item = _list_0[_index_0]
976 _accum_0[_len_0] = item 1143 _accum_0[_len_0] = item
977 _len_0 = _len_0 + 1 1144 _len_0 = _len_0 + 1
@@ -981,7 +1148,8 @@ local slice
981local _accum_0 = { } 1148local _accum_0 = { }
982local _len_0 = 1 1149local _len_0 = 1
983local _list_0 = items 1150local _list_0 = items
984for _index_0 = 2, #_list_0 do 1151local _max_0 = #_list_0
1152for _index_0 = 2, _max_0 do
985 local item = _list_0[_index_0] 1153 local item = _list_0[_index_0]
986 _accum_0[_len_0] = item 1154 _accum_0[_len_0] = item
987 _len_0 = _len_0 + 1 1155 _len_0 = _len_0 + 1
@@ -991,12 +1159,46 @@ local slice
991local _accum_0 = { } 1159local _accum_0 = { }
992local _len_0 = 1 1160local _len_0 = 1
993local _list_0 = items 1161local _list_0 = items
994for _index_0 = 1, #_list_0, 2 do 1162local _max_0 = #_list_0
1163for _index_0 = 1, _max_0, 2 do
995 local item = _list_0[_index_0] 1164 local item = _list_0[_index_0]
996 _accum_0[_len_0] = item 1165 _accum_0[_len_0] = item
997 _len_0 = _len_0 + 1 1166 _len_0 = _len_0 + 1
998end 1167end
999slice = _accum_0 1168slice = _accum_0
1169local slice
1170local _accum_0 = { }
1171local _len_0 = 1
1172local _list_0 = items
1173local _min_0 = #_list_0 + -4 + 1
1174local _max_0 = #_list_0 + -1 + 1
1175for _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
1179end
1180slice = _accum_0
1181local reverse_slice
1182local _accum_0 = { }
1183local _len_0 = 1
1184local _list_0 = items
1185local _min_0 = #_list_0 + -1 + 1
1186for _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
1190end
1191reverse_slice = _accum_0
1192local sub_list
1193local _accum_0 = { }
1194local _len_0 = 1
1195local _list_0 = items
1196for _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
1200end
1201sub_list = _accum_0
1000for i = 10, 20 do 1202for i = 10, 20 do
1001 print(i) 1203 print(i)
1002end 1204end
@@ -1007,8 +1209,7 @@ for key, value in pairs(object) do
1007 print(key, value) 1209 print(key, value)
1008end 1210end
1009local _list_0 = items 1211local _list_0 = items
1010local _max_0 = 4 1212for _index_0 = 2, 4 do
1011for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do
1012 local item = _list_0[_index_0] 1213 local item = _list_0[_index_0]
1013 print(item) 1214 print(item)
1014end 1215end
@@ -1026,12 +1227,24 @@ local _len_0 = 1
1026for i = 1, 20 do 1227for i = 1, 20 do
1027 if i % 2 == 0 then 1228 if i % 2 == 0 then
1028 _accum_0[_len_0] = i * 2 1229 _accum_0[_len_0] = i * 2
1230 _len_0 = _len_0 + 1
1029 else 1231 else
1030 _accum_0[_len_0] = i 1232 _accum_0[_len_0] = i
1233 _len_0 = _len_0 + 1
1031 end 1234 end
1032 _len_0 = _len_0 + 1
1033end 1235end
1034doubled_evens = _accum_0 1236doubled_evens = _accum_0
1237local first_large
1238local _accum_0
1239local _list_0 = numbers
1240for _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
1246end
1247first_large = _accum_0
1035local func_a 1248local func_a
1036func_a = function() 1249func_a = function()
1037 for i = 1, 10 do 1250 for i = 1, 10 do
@@ -1180,7 +1393,7 @@ if "Robert" == name then
1180elseif "Dan" == name or "Daniel" == name then 1393elseif "Dan" == name or "Daniel" == name then
1181 print("Your name, it's Dan") 1394 print("Your name, it's Dan")
1182else 1395else
1183 print("I don't know about your name") 1396 print("I don't know about you with name " .. tostring(name))
1184end 1397end
1185local b = 1 1398local b = 1
1186local next_number 1399local next_number
@@ -1280,6 +1493,192 @@ if _tab_0 then
1280 end 1493 end
1281 print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) 1494 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
1282end 1495end
1496local _exp_0 = tb
1497local _type_0 = type(_exp_0)
1498local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1499local _match_0 = false
1500if _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
1505end
1506if 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
1526end
1527local _exp_0 = tb
1528local _type_0 = type(_exp_0)
1529local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1530local _match_0 = false
1531if _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
1537end
1538if 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
1549end
1550local _exp_0 = tb
1551local _type_0 = type(_exp_0)
1552local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1553local _match_0 = false
1554if _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
1574end
1575if 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
1601end
1602local _exp_0 = tb
1603local _type_0 = type(_exp_0)
1604local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1605if _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
1652end
1653local segments = {
1654 "admin",
1655 "users",
1656 "logs",
1657 "view"
1658}
1659local _type_0 = type(segments)
1660local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1661if _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
1681end
1283local Inventory 1682local Inventory
1284local _class_0 1683local _class_0
1285local _base_0 = { 1684local _base_0 = {
@@ -1936,6 +2335,10 @@ do
1936 _with_1["key-name"] = value 2335 _with_1["key-name"] = value
1937end 2336end
1938_with_0[#_with_0 + 1] = "abc" 2337_with_0[#_with_0 + 1] = "abc"
2338local _with_0 = obj
2339if _with_0 ~= nil then
2340 print(obj.name)
2341end
1939do 2342do
1940 local var = "hello" 2343 local var = "hello"
1941 print(var) 2344 print(var)
@@ -2026,6 +2429,38 @@ local inventory = {
2026 } 2429 }
2027 } 2430 }
2028} 2431}
2432local map
2433map = 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
2442end
2443local filter
2444filter = 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
2455end
2456local reduce
2457reduce = 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
2463end
2029print(reduce(filter(map({ 2464print(reduce(filter(map({
2030 1, 2465 1,
2031 2, 2466 2,
@@ -2083,6 +2518,12 @@ end
2083print("yuescript") 2518print("yuescript")
2084print(3) 2519print(3)
2085print("Valid enum type:", "Static") 2520print("Valid enum type:", "Static")
2521do
2522 print(123, "hello")
2523end
2524do
2525 print(123, "hello")
2526end
2086if tb ~= nil then 2527if tb ~= nil then
2087 tb:func() 2528 tb:func()
2088end 2529end
@@ -2183,6 +2624,16 @@ for _key_0, _value_0 in pairs(b) do
2183 end 2624 end
2184end 2625end
2185merge = _tab_0 2626merge = _tab_0
2627local last
2628do
2629 local _item_0 = data.items
2630 last = _item_0[#_item_0]
2631end
2632local second_last
2633do
2634 local _item_0 = data.items
2635 second_last = _item_0[#_item_0 - 1]
2636end
2186local mt = { } 2637local mt = { }
2187local add 2638local add
2188add = function(self, right) 2639add = function(self, right)
@@ -2313,6 +2764,14 @@ func({
2313 2, 2764 2,
2314 3 2765 3
2315}) 2766})
2767local f
2768f = function()
2769 return {
2770 1,
2771 2,
2772 3
2773 }
2774end
2316local tb = { 2775local tb = {
2317 name = "abc", 2776 name = "abc",
2318 values = { 2777 values = {
@@ -2553,6 +3012,59 @@ end
2553local two, four 3012local two, four
2554local _obj_0 = items 3013local _obj_0 = items
2555two, four = _obj_0[2], _obj_0[4] 3014two, four = _obj_0[2], _obj_0[4]
3015local orders = {
3016 "first",
3017 "second",
3018 "third",
3019 "fourth",
3020 "last"
3021}
3022local 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
3032end)(), orders[#orders]
3033print(first)
3034print(bulk)
3035print(last)
3036local first, rest
3037do
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)()
3050end
3051local start, last
3052do
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]
3065end
3066local _obj_0 = orders
3067first, last = _obj_0[1], _obj_0[#_obj_0]
2556local tuples = { 3068local tuples = {
2557 { 3069 {
2558 "hello", 3070 "hello",
@@ -2654,6 +3166,56 @@ end)
2654if success then 3166if success then
2655 print(result) 3167 print(result)
2656end 3168end
3169local a, b, c
3170do
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
3177end
3178do
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
3194end
3195f((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))
3204end)())
3205f((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))
3218end)())
2657local a <const> = 123 3219local a <const> = 123
2658local _ <close> = setmetatable({ }, { 3220local _ <close> = setmetatable({ }, {
2659 __close = function() 3221 __close = function()
@@ -2663,10 +3225,19 @@ local _ <close> = setmetatable({ }, {
2663local a, b, c, d 3225local a, b, c, d
2664local _obj_0 = tb 3226local _obj_0 = tb
2665a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] 3227a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
3228Constant = 123
2666local some_string = "Here is a string\n that has a line break in it." 3229local some_string = "Here is a string\n that has a line break in it."
2667print("I am " .. tostring(math.random() * 100) .. "% sure.") 3230print("I am " .. tostring(math.random() * 100) .. "% sure.")
2668local integer = 1000000 3231local integer = 1000000
2669local hex = 0xEFBBBF 3232local hex = 0xEFBBBF
3233local binary = 19
3234local str = "key: value\nlist:\n - item1\n - " .. tostring(expr)
3235local fn
3236fn = function()
3237 local str = "foo:\n bar: baz"
3238 return str
3239end
3240local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
2670local my_function 3241local my_function
2671my_function = function() end 3242my_function = function() end
2672my_function() 3243my_function()
@@ -2976,8 +3547,7 @@ local slice
2976local _accum_0 = { } 3547local _accum_0 = { }
2977local _len_0 = 1 3548local _len_0 = 1
2978local _list_0 = items 3549local _list_0 = items
2979local _max_0 = 5 3550for _index_0 = 1, 5 do
2980for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do
2981 local item = _list_0[_index_0] 3551 local item = _list_0[_index_0]
2982 _accum_0[_len_0] = item 3552 _accum_0[_len_0] = item
2983 _len_0 = _len_0 + 1 3553 _len_0 = _len_0 + 1
@@ -2987,7 +3557,8 @@ local slice
2987local _accum_0 = { } 3557local _accum_0 = { }
2988local _len_0 = 1 3558local _len_0 = 1
2989local _list_0 = items 3559local _list_0 = items
2990for _index_0 = 2, #_list_0 do 3560local _max_0 = #_list_0
3561for _index_0 = 2, _max_0 do
2991 local item = _list_0[_index_0] 3562 local item = _list_0[_index_0]
2992 _accum_0[_len_0] = item 3563 _accum_0[_len_0] = item
2993 _len_0 = _len_0 + 1 3564 _len_0 = _len_0 + 1
@@ -2997,12 +3568,46 @@ local slice
2997local _accum_0 = { } 3568local _accum_0 = { }
2998local _len_0 = 1 3569local _len_0 = 1
2999local _list_0 = items 3570local _list_0 = items
3000for _index_0 = 1, #_list_0, 2 do 3571local _max_0 = #_list_0
3572for _index_0 = 1, _max_0, 2 do
3001 local item = _list_0[_index_0] 3573 local item = _list_0[_index_0]
3002 _accum_0[_len_0] = item 3574 _accum_0[_len_0] = item
3003 _len_0 = _len_0 + 1 3575 _len_0 = _len_0 + 1
3004end 3576end
3005slice = _accum_0 3577slice = _accum_0
3578local slice
3579local _accum_0 = { }
3580local _len_0 = 1
3581local _list_0 = items
3582local _min_0 = #_list_0 + -4 + 1
3583local _max_0 = #_list_0 + -1 + 1
3584for _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
3588end
3589slice = _accum_0
3590local reverse_slice
3591local _accum_0 = { }
3592local _len_0 = 1
3593local _list_0 = items
3594local _min_0 = #_list_0 + -1 + 1
3595for _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
3599end
3600reverse_slice = _accum_0
3601local sub_list
3602local _accum_0 = { }
3603local _len_0 = 1
3604local _list_0 = items
3605for _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
3609end
3610sub_list = _accum_0
3006for i = 10, 20 do 3611for i = 10, 20 do
3007 print(i) 3612 print(i)
3008end 3613end
@@ -3013,8 +3618,7 @@ for key, value in pairs(object) do
3013 print(key, value) 3618 print(key, value)
3014end 3619end
3015local _list_0 = items 3620local _list_0 = items
3016local _max_0 = 4 3621for _index_0 = 2, 4 do
3017for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do
3018 local item = _list_0[_index_0] 3622 local item = _list_0[_index_0]
3019 print(item) 3623 print(item)
3020end 3624end
@@ -3032,12 +3636,24 @@ local _len_0 = 1
3032for i = 1, 20 do 3636for i = 1, 20 do
3033 if i % 2 == 0 then 3637 if i % 2 == 0 then
3034 _accum_0[_len_0] = i * 2 3638 _accum_0[_len_0] = i * 2
3639 _len_0 = _len_0 + 1
3035 else 3640 else
3036 _accum_0[_len_0] = i 3641 _accum_0[_len_0] = i
3642 _len_0 = _len_0 + 1
3037 end 3643 end
3038 _len_0 = _len_0 + 1
3039end 3644end
3040doubled_evens = _accum_0 3645doubled_evens = _accum_0
3646local first_large
3647local _accum_0
3648local _list_0 = numbers
3649for _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
3655end
3656first_large = _accum_0
3041local func_a 3657local func_a
3042func_a = function() 3658func_a = function()
3043 for i = 1, 10 do 3659 for i = 1, 10 do
@@ -3186,7 +3802,7 @@ if "Robert" == name then
3186elseif "Dan" == name or "Daniel" == name then 3802elseif "Dan" == name or "Daniel" == name then
3187 print("Your name, it's Dan") 3803 print("Your name, it's Dan")
3188else 3804else
3189 print("I don't know about your name") 3805 print("I don't know about you with name " .. tostring(name))
3190end 3806end
3191local b = 1 3807local b = 1
3192local next_number 3808local next_number
@@ -3286,6 +3902,192 @@ if _tab_0 then
3286 end 3902 end
3287 print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) 3903 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
3288end 3904end
3905local _exp_0 = tb
3906local _type_0 = type(_exp_0)
3907local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3908local _match_0 = false
3909if _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
3914end
3915if 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
3935end
3936local _exp_0 = tb
3937local _type_0 = type(_exp_0)
3938local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3939local _match_0 = false
3940if _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
3946end
3947if 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
3958end
3959local _exp_0 = tb
3960local _type_0 = type(_exp_0)
3961local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3962local _match_0 = false
3963if _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
3983end
3984if 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
4010end
4011local _exp_0 = tb
4012local _type_0 = type(_exp_0)
4013local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4014if _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
4061end
4062local segments = {
4063 "admin",
4064 "users",
4065 "logs",
4066 "view"
4067}
4068local _type_0 = type(segments)
4069local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4070if _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
4090end
3289local Inventory 4091local Inventory
3290local _class_0 4092local _class_0
3291local _base_0 = { 4093local _base_0 = {
@@ -3942,6 +4744,10 @@ do
3942 _with_1["key-name"] = value 4744 _with_1["key-name"] = value
3943end 4745end
3944_with_0[#_with_0 + 1] = "abc" 4746_with_0[#_with_0 + 1] = "abc"
4747local _with_0 = obj
4748if _with_0 ~= nil then
4749 print(obj.name)
4750end
3945do 4751do
3946 local var = "hello" 4752 local var = "hello"
3947 print(var) 4753 print(var)
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua
index acd41a0..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}
23local map
24map = 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
33end
34local filter
35filter = 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
46end
47local reduce
48reduce = 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
54end
23print(reduce(filter(map({ 55print(reduce(filter(map({
24 1, 56 1,
25 2, 57 2,
@@ -77,6 +109,12 @@ end
77print("yuescript") 109print("yuescript")
78print(3) 110print(3)
79print("ζœ‰ζ•ˆηš„ζžšδΈΎη±»εž‹:", "Static") 111print("ζœ‰ζ•ˆηš„ζžšδΈΎη±»εž‹:", "Static")
112do
113 print(123, "hello")
114end
115do
116 print(123, "hello")
117end
80if tb ~= nil then 118if tb ~= nil then
81 tb:func() 119 tb:func()
82end 120end
@@ -177,6 +215,16 @@ for _key_0, _value_0 in pairs(b) do
177 end 215 end
178end 216end
179merge = _tab_0 217merge = _tab_0
218local last
219do
220 local _item_0 = data.items
221 last = _item_0[#_item_0]
222end
223local second_last
224do
225 local _item_0 = data.items
226 second_last = _item_0[#_item_0 - 1]
227end
180local mt = { } 228local mt = { }
181local add 229local add
182add = function(self, right) 230add = function(self, right)
@@ -307,6 +355,14 @@ func({
307 2, 355 2,
308 3 356 3
309}) 357})
358local f
359f = function()
360 return {
361 1,
362 2,
363 3
364 }
365end
310local tb = { 366local tb = {
311 name = "abc", 367 name = "abc",
312 values = { 368 values = {
@@ -547,6 +603,59 @@ end
547local two, four 603local two, four
548local _obj_0 = items 604local _obj_0 = items
549two, four = _obj_0[2], _obj_0[4] 605two, four = _obj_0[2], _obj_0[4]
606local orders = {
607 "first",
608 "second",
609 "third",
610 "fourth",
611 "last"
612}
613local 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
623end)(), orders[#orders]
624print(first)
625print(bulk)
626print(last)
627local first, rest
628do
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)()
641end
642local start, last
643do
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]
656end
657local _obj_0 = orders
658first, last = _obj_0[1], _obj_0[#_obj_0]
550local tuples = { 659local tuples = {
551 { 660 {
552 "hello", 661 "hello",
@@ -648,6 +757,56 @@ end)
648if success then 757if success then
649 print(result) 758 print(result)
650end 759end
760local a, b, c
761do
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
768end
769do
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
785end
786f((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))
795end)())
796f((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))
809end)())
651local a <const> = 123 810local a <const> = 123
652local _ <close> = setmetatable({ }, { 811local _ <close> = setmetatable({ }, {
653 __close = function() 812 __close = function()
@@ -657,10 +816,19 @@ local _ <close> = setmetatable({ }, {
657local a, b, c, d 816local a, b, c, d
658local _obj_0 = tb 817local _obj_0 = tb
659a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] 818a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
819Constant = 123
660local some_string = "θΏ™ζ˜―δΈ€δΈͺ字符串\n εΉΆεŒ…ζ‹¬δΈ€δΈͺζ’θ‘Œγ€‚" 820local some_string = "θΏ™ζ˜―δΈ€δΈͺ字符串\n εΉΆεŒ…ζ‹¬δΈ€δΈͺζ’θ‘Œγ€‚"
661print("ζˆ‘ζœ‰" .. tostring(math.random() * 100) .. "%ηš„ζŠŠζ‘γ€‚") 821print("ζˆ‘ζœ‰" .. tostring(math.random() * 100) .. "%ηš„ζŠŠζ‘γ€‚")
662local integer = 1000000 822local integer = 1000000
663local hex = 0xEFBBBF 823local hex = 0xEFBBBF
824local binary = 19
825local str = "key: value\nlist:\n - item1\n - " .. tostring(expr)
826local fn
827fn = function()
828 local str = "foo:\n bar: baz"
829 return str
830end
831local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
664local my_function 832local my_function
665my_function = function() end 833my_function = function() end
666my_function() 834my_function()
@@ -964,8 +1132,7 @@ local slice
964local _accum_0 = { } 1132local _accum_0 = { }
965local _len_0 = 1 1133local _len_0 = 1
966local _list_0 = items 1134local _list_0 = items
967local _max_0 = 5 1135for _index_0 = 1, 5 do
968for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do
969 local item = _list_0[_index_0] 1136 local item = _list_0[_index_0]
970 _accum_0[_len_0] = item 1137 _accum_0[_len_0] = item
971 _len_0 = _len_0 + 1 1138 _len_0 = _len_0 + 1
@@ -975,7 +1142,8 @@ local slice
975local _accum_0 = { } 1142local _accum_0 = { }
976local _len_0 = 1 1143local _len_0 = 1
977local _list_0 = items 1144local _list_0 = items
978for _index_0 = 2, #_list_0 do 1145local _max_0 = #_list_0
1146for _index_0 = 2, _max_0 do
979 local item = _list_0[_index_0] 1147 local item = _list_0[_index_0]
980 _accum_0[_len_0] = item 1148 _accum_0[_len_0] = item
981 _len_0 = _len_0 + 1 1149 _len_0 = _len_0 + 1
@@ -985,12 +1153,46 @@ local slice
985local _accum_0 = { } 1153local _accum_0 = { }
986local _len_0 = 1 1154local _len_0 = 1
987local _list_0 = items 1155local _list_0 = items
988for _index_0 = 1, #_list_0, 2 do 1156local _max_0 = #_list_0
1157for _index_0 = 1, _max_0, 2 do
989 local item = _list_0[_index_0] 1158 local item = _list_0[_index_0]
990 _accum_0[_len_0] = item 1159 _accum_0[_len_0] = item
991 _len_0 = _len_0 + 1 1160 _len_0 = _len_0 + 1
992end 1161end
993slice = _accum_0 1162slice = _accum_0
1163local slice
1164local _accum_0 = { }
1165local _len_0 = 1
1166local _list_0 = items
1167local _min_0 = #_list_0 + -4 + 1
1168local _max_0 = #_list_0 + -1 + 1
1169for _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
1173end
1174slice = _accum_0
1175local reverse_slice
1176local _accum_0 = { }
1177local _len_0 = 1
1178local _list_0 = items
1179local _min_0 = #_list_0 + -1 + 1
1180for _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
1184end
1185reverse_slice = _accum_0
1186local sub_list
1187local _accum_0 = { }
1188local _len_0 = 1
1189local _list_0 = items
1190for _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
1194end
1195sub_list = _accum_0
994for i = 10, 20 do 1196for i = 10, 20 do
995 print(i) 1197 print(i)
996end 1198end
@@ -1001,8 +1203,7 @@ for key, value in pairs(object) do
1001 print(key, value) 1203 print(key, value)
1002end 1204end
1003local _list_0 = items 1205local _list_0 = items
1004local _max_0 = 4 1206for _index_0 = 2, 4 do
1005for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do
1006 local item = _list_0[_index_0] 1207 local item = _list_0[_index_0]
1007 print(item) 1208 print(item)
1008end 1209end
@@ -1020,12 +1221,24 @@ local _len_0 = 1
1020for i = 1, 20 do 1221for i = 1, 20 do
1021 if i % 2 == 0 then 1222 if i % 2 == 0 then
1022 _accum_0[_len_0] = i * 2 1223 _accum_0[_len_0] = i * 2
1224 _len_0 = _len_0 + 1
1023 else 1225 else
1024 _accum_0[_len_0] = i 1226 _accum_0[_len_0] = i
1227 _len_0 = _len_0 + 1
1025 end 1228 end
1026 _len_0 = _len_0 + 1
1027end 1229end
1028doubled_evens = _accum_0 1230doubled_evens = _accum_0
1231local first_large
1232local _accum_0
1233local _list_0 = numbers
1234for _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
1240end
1241first_large = _accum_0
1029local func_a 1242local func_a
1030func_a = function() 1243func_a = function()
1031 for i = 1, 10 do 1244 for i = 1, 10 do
@@ -1174,7 +1387,7 @@ if "Robert" == name then
1174elseif "Dan" == name or "Daniel" == name then 1387elseif "Dan" == name or "Daniel" == name then
1175 print("δ½ ηš„εε­—ζ˜―Dan") 1388 print("δ½ ηš„εε­—ζ˜―Dan")
1176else 1389else
1177 print("ζˆ‘δΈηŸ₯ι“δ½ ηš„εε­—") 1390 print("ζˆ‘δΈθ€θ―†δ½ οΌŒδ½ ηš„εε­—ζ˜―" .. tostring(name))
1178end 1391end
1179local b = 1 1392local b = 1
1180local next_number 1393local next_number
@@ -1274,6 +1487,192 @@ if _tab_0 then
1274 end 1487 end
1275 print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) 1488 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
1276end 1489end
1490local _exp_0 = tb
1491local _type_0 = type(_exp_0)
1492local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1493local _match_0 = false
1494if _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
1499end
1500if 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
1520end
1521local _exp_0 = tb
1522local _type_0 = type(_exp_0)
1523local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1524local _match_0 = false
1525if _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
1531end
1532if 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
1543end
1544local _exp_0 = tb
1545local _type_0 = type(_exp_0)
1546local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1547local _match_0 = false
1548if _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
1568end
1569if 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
1595end
1596local _exp_0 = tb
1597local _type_0 = type(_exp_0)
1598local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1599if _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
1646end
1647local segments = {
1648 "admin",
1649 "users",
1650 "logs",
1651 "view"
1652}
1653local _type_0 = type(segments)
1654local _tab_0 = "table" == _type_0 or "userdata" == _type_0
1655if _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
1675end
1277local Inventory 1676local Inventory
1278local _class_0 1677local _class_0
1279local _base_0 = { 1678local _base_0 = {
@@ -1930,6 +2329,10 @@ do
1930 _with_1["key-name"] = value 2329 _with_1["key-name"] = value
1931end 2330end
1932_with_0[#_with_0 + 1] = "abc" 2331_with_0[#_with_0 + 1] = "abc"
2332local _with_0 = obj
2333if _with_0 ~= nil then
2334 print(obj.name)
2335end
1933do 2336do
1934 local var = "hello" 2337 local var = "hello"
1935 print(var) 2338 print(var)
@@ -2020,6 +2423,38 @@ local inventory = {
2020 } 2423 }
2021 } 2424 }
2022} 2425}
2426local map
2427map = 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
2436end
2437local filter
2438filter = 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
2449end
2450local reduce
2451reduce = 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
2457end
2023print(reduce(filter(map({ 2458print(reduce(filter(map({
2024 1, 2459 1,
2025 2, 2460 2,
@@ -2077,6 +2512,12 @@ end
2077print("yuescript") 2512print("yuescript")
2078print(3) 2513print(3)
2079print("ζœ‰ζ•ˆηš„ζžšδΈΎη±»εž‹:", "Static") 2514print("ζœ‰ζ•ˆηš„ζžšδΈΎη±»εž‹:", "Static")
2515do
2516 print(123, "hello")
2517end
2518do
2519 print(123, "hello")
2520end
2080if tb ~= nil then 2521if tb ~= nil then
2081 tb:func() 2522 tb:func()
2082end 2523end
@@ -2177,6 +2618,16 @@ for _key_0, _value_0 in pairs(b) do
2177 end 2618 end
2178end 2619end
2179merge = _tab_0 2620merge = _tab_0
2621local last
2622do
2623 local _item_0 = data.items
2624 last = _item_0[#_item_0]
2625end
2626local second_last
2627do
2628 local _item_0 = data.items
2629 second_last = _item_0[#_item_0 - 1]
2630end
2180local mt = { } 2631local mt = { }
2181local add 2632local add
2182add = function(self, right) 2633add = function(self, right)
@@ -2307,6 +2758,14 @@ func({
2307 2, 2758 2,
2308 3 2759 3
2309}) 2760})
2761local f
2762f = function()
2763 return {
2764 1,
2765 2,
2766 3
2767 }
2768end
2310local tb = { 2769local tb = {
2311 name = "abc", 2770 name = "abc",
2312 values = { 2771 values = {
@@ -2547,6 +3006,59 @@ end
2547local two, four 3006local two, four
2548local _obj_0 = items 3007local _obj_0 = items
2549two, four = _obj_0[2], _obj_0[4] 3008two, four = _obj_0[2], _obj_0[4]
3009local orders = {
3010 "first",
3011 "second",
3012 "third",
3013 "fourth",
3014 "last"
3015}
3016local 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
3026end)(), orders[#orders]
3027print(first)
3028print(bulk)
3029print(last)
3030local first, rest
3031do
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)()
3044end
3045local start, last
3046do
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]
3059end
3060local _obj_0 = orders
3061first, last = _obj_0[1], _obj_0[#_obj_0]
2550local tuples = { 3062local tuples = {
2551 { 3063 {
2552 "hello", 3064 "hello",
@@ -2648,6 +3160,56 @@ end)
2648if success then 3160if success then
2649 print(result) 3161 print(result)
2650end 3162end
3163local a, b, c
3164do
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
3171end
3172do
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
3188end
3189f((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))
3198end)())
3199f((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))
3212end)())
2651local a <const> = 123 3213local a <const> = 123
2652local _ <close> = setmetatable({ }, { 3214local _ <close> = setmetatable({ }, {
2653 __close = function() 3215 __close = function()
@@ -2657,10 +3219,19 @@ local _ <close> = setmetatable({ }, {
2657local a, b, c, d 3219local a, b, c, d
2658local _obj_0 = tb 3220local _obj_0 = tb
2659a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] 3221a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
3222Constant = 123
2660local some_string = "θΏ™ζ˜―δΈ€δΈͺ字符串\n εΉΆεŒ…ζ‹¬δΈ€δΈͺζ’θ‘Œγ€‚" 3223local some_string = "θΏ™ζ˜―δΈ€δΈͺ字符串\n εΉΆεŒ…ζ‹¬δΈ€δΈͺζ’θ‘Œγ€‚"
2661print("ζˆ‘ζœ‰" .. tostring(math.random() * 100) .. "%ηš„ζŠŠζ‘γ€‚") 3224print("ζˆ‘ζœ‰" .. tostring(math.random() * 100) .. "%ηš„ζŠŠζ‘γ€‚")
2662local integer = 1000000 3225local integer = 1000000
2663local hex = 0xEFBBBF 3226local hex = 0xEFBBBF
3227local binary = 19
3228local str = "key: value\nlist:\n - item1\n - " .. tostring(expr)
3229local fn
3230fn = function()
3231 local str = "foo:\n bar: baz"
3232 return str
3233end
3234local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
2664local my_function 3235local my_function
2665my_function = function() end 3236my_function = function() end
2666my_function() 3237my_function()
@@ -2964,8 +3535,7 @@ local slice
2964local _accum_0 = { } 3535local _accum_0 = { }
2965local _len_0 = 1 3536local _len_0 = 1
2966local _list_0 = items 3537local _list_0 = items
2967local _max_0 = 5 3538for _index_0 = 1, 5 do
2968for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do
2969 local item = _list_0[_index_0] 3539 local item = _list_0[_index_0]
2970 _accum_0[_len_0] = item 3540 _accum_0[_len_0] = item
2971 _len_0 = _len_0 + 1 3541 _len_0 = _len_0 + 1
@@ -2975,7 +3545,8 @@ local slice
2975local _accum_0 = { } 3545local _accum_0 = { }
2976local _len_0 = 1 3546local _len_0 = 1
2977local _list_0 = items 3547local _list_0 = items
2978for _index_0 = 2, #_list_0 do 3548local _max_0 = #_list_0
3549for _index_0 = 2, _max_0 do
2979 local item = _list_0[_index_0] 3550 local item = _list_0[_index_0]
2980 _accum_0[_len_0] = item 3551 _accum_0[_len_0] = item
2981 _len_0 = _len_0 + 1 3552 _len_0 = _len_0 + 1
@@ -2985,12 +3556,46 @@ local slice
2985local _accum_0 = { } 3556local _accum_0 = { }
2986local _len_0 = 1 3557local _len_0 = 1
2987local _list_0 = items 3558local _list_0 = items
2988for _index_0 = 1, #_list_0, 2 do 3559local _max_0 = #_list_0
3560for _index_0 = 1, _max_0, 2 do
2989 local item = _list_0[_index_0] 3561 local item = _list_0[_index_0]
2990 _accum_0[_len_0] = item 3562 _accum_0[_len_0] = item
2991 _len_0 = _len_0 + 1 3563 _len_0 = _len_0 + 1
2992end 3564end
2993slice = _accum_0 3565slice = _accum_0
3566local slice
3567local _accum_0 = { }
3568local _len_0 = 1
3569local _list_0 = items
3570local _min_0 = #_list_0 + -4 + 1
3571local _max_0 = #_list_0 + -1 + 1
3572for _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
3576end
3577slice = _accum_0
3578local reverse_slice
3579local _accum_0 = { }
3580local _len_0 = 1
3581local _list_0 = items
3582local _min_0 = #_list_0 + -1 + 1
3583for _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
3587end
3588reverse_slice = _accum_0
3589local sub_list
3590local _accum_0 = { }
3591local _len_0 = 1
3592local _list_0 = items
3593for _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
3597end
3598sub_list = _accum_0
2994for i = 10, 20 do 3599for i = 10, 20 do
2995 print(i) 3600 print(i)
2996end 3601end
@@ -3001,8 +3606,7 @@ for key, value in pairs(object) do
3001 print(key, value) 3606 print(key, value)
3002end 3607end
3003local _list_0 = items 3608local _list_0 = items
3004local _max_0 = 4 3609for _index_0 = 2, 4 do
3005for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do
3006 local item = _list_0[_index_0] 3610 local item = _list_0[_index_0]
3007 print(item) 3611 print(item)
3008end 3612end
@@ -3020,12 +3624,24 @@ local _len_0 = 1
3020for i = 1, 20 do 3624for i = 1, 20 do
3021 if i % 2 == 0 then 3625 if i % 2 == 0 then
3022 _accum_0[_len_0] = i * 2 3626 _accum_0[_len_0] = i * 2
3627 _len_0 = _len_0 + 1
3023 else 3628 else
3024 _accum_0[_len_0] = i 3629 _accum_0[_len_0] = i
3630 _len_0 = _len_0 + 1
3025 end 3631 end
3026 _len_0 = _len_0 + 1
3027end 3632end
3028doubled_evens = _accum_0 3633doubled_evens = _accum_0
3634local first_large
3635local _accum_0
3636local _list_0 = numbers
3637for _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
3643end
3644first_large = _accum_0
3029local func_a 3645local func_a
3030func_a = function() 3646func_a = function()
3031 for i = 1, 10 do 3647 for i = 1, 10 do
@@ -3174,7 +3790,7 @@ if "Robert" == name then
3174elseif "Dan" == name or "Daniel" == name then 3790elseif "Dan" == name or "Daniel" == name then
3175 print("δ½ ηš„εε­—ζ˜―Dan") 3791 print("δ½ ηš„εε­—ζ˜―Dan")
3176else 3792else
3177 print("ζˆ‘δΈηŸ₯ι“δ½ ηš„εε­—") 3793 print("ζˆ‘δΈθ€θ―†δ½ οΌŒδ½ ηš„εε­—ζ˜―" .. tostring(name))
3178end 3794end
3179local b = 1 3795local b = 1
3180local next_number 3796local next_number
@@ -3274,6 +3890,192 @@ if _tab_0 then
3274 end 3890 end
3275 print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) 3891 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
3276end 3892end
3893local _exp_0 = tb
3894local _type_0 = type(_exp_0)
3895local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3896local _match_0 = false
3897if _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
3902end
3903if 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
3923end
3924local _exp_0 = tb
3925local _type_0 = type(_exp_0)
3926local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3927local _match_0 = false
3928if _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
3934end
3935if 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
3946end
3947local _exp_0 = tb
3948local _type_0 = type(_exp_0)
3949local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3950local _match_0 = false
3951if _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
3971end
3972if 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
3998end
3999local _exp_0 = tb
4000local _type_0 = type(_exp_0)
4001local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4002if _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
4049end
4050local segments = {
4051 "admin",
4052 "users",
4053 "logs",
4054 "view"
4055}
4056local _type_0 = type(segments)
4057local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4058if _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
4078end
3277local Inventory 4079local Inventory
3278local _class_0 4080local _class_0
3279local _base_0 = { 4081local _base_0 = {
@@ -3930,6 +4732,10 @@ do
3930 _with_1["key-name"] = value 4732 _with_1["key-name"] = value
3931end 4733end
3932_with_0[#_with_0 + 1] = "abc" 4734_with_0[#_with_0 + 1] = "abc"
4735local _with_0 = obj
4736if _with_0 ~= nil then
4737 print(obj.name)
4738end
3933do 4739do
3934 local var = "hello" 4740 local var = "hello"
3935 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
243do 243do
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
254do 257do
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
623end 623end
624do
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)
645end
646do
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 })
658end
659do
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)
685end
686do
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
698end
699do
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]
713end
624return nil 714return 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"
95end 95end
96do
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
120end
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
168end 168end
169do
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["月"]
178end
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}
233local _max_0 = -5 233local _max_0 = #x + -5 + 1
234for _index_0 = 2, _max_0 < 0 and #x + _max_0 or _max_0, 2 do 234for _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)
237end 237end
238local _max_1 = 3 238for _index_0 = 1, 3 do
239for _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)
242end 241end
243for _index_0 = 2, #x do 242local _max_1 = #x
243for _index_0 = 2, _max_1 do
244 local y = x[_index_0] 244 local y = x[_index_0]
245 print(y) 245 print(y)
246end 246end
247for _index_0 = 1, #x, 2 do 247local _max_2 = #x
248for _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)
250end 251end
251for _index_0 = 2, #x, 2 do 252local _max_3 = #x
253for _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)
254end 256end
255local a, b, c = 1, 5, 2 257local a, b, c = 1, 5, 2
256local _max_2 = b 258local _min_0 = a
257for _index_0 = a, _max_2 < 0 and #x + _max_2 or _max_2, c do 259local _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
262for _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)
260end 265end
@@ -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
329end 337end
338do
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)
359end
360do
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"])
376end
377do
378 local pendingOrders = {
379 "O001",
380 "O002",
381 "O003",
382 "O004"
383 }
384 print(pendingOrders[#pendingOrders - 1])
385end
386do
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")
410end
411do
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
449end
450do
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)())
471end
472local _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)
476end
477local _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]
492end
493local _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
518end
519do
520 local f
521 f = function()
522 return print(_anon_func_0(globalTB), _anon_func_1(a), _anon_func_2(x))
523 end
524end
330return nil 525return nil
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
67end 67end
@@ -132,13 +132,11 @@ do
132end 132end
133do 133do
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
144end 142end
@@ -370,3 +368,131 @@ do
370 end 368 end
371 until false 369 until false
372end 370end
371local _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
380end
381do
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
470end
471do
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
498end
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})
29print({
30 456,
31 'abc'
32})
29do 33do
30 assert(item == nil) 34 assert(item == nil)
31end 35end
@@ -213,6 +217,13 @@ function tb:func()
213end 217end
214end 218end
215print(x) 219print(x)
220local yue = require("yue")
221do
222local function f2(a)
223 return a + 1
224end
225x = x + f2(3)
226end
216local sel 227local sel
217sel = function(a, b, c) 228sel = 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}))
320print("current line: " .. tostring(323)) 331print("current line: " .. tostring(349))
321do 332do
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
339end 348end
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 @@
1local Props
2do
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
132end
133local A
134do
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
186end
187local B
188do
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
237end
238local b = B()
239b.x = 999
240return 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 @@
1local _module_0 = { }
1local hi = "hello" 2local hi = "hello"
2local hello = "what the heckyes" 3local hello = "what the heckyes"
3print(hi) 4print(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)
43something("hello"):world() 44something("hello"):world()
44return something(("hello"):world()) 45something(("hello"):world())
46do
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"))
80end
81local yaml = "version: " .. tostring(ver) .. "\nok: true"
82_module_0["yaml"] = yaml
83return _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
417end 417end
418do
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
450end
451do
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
475end
476do
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
501end
502do
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
658end
659do
660 local v = "hello"
661 if "hello" == v then
662 print("matched hello")
663 else
664 print("not matched")
665 end
666end
667do
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
676end
677do
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
690end
691do
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
706end
707do
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
729end
730do
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
759end
760do
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 })
779end
418return nil 780return 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}
369local tb 391local tb
370do 392do
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
22local _anon_func_7 = function(a, b, c, tb) 22local _anon_func_7 = function(a, b, c, tb)
23 return tb.f(a, b, c) 23 return tb.f(a, b, c)
24end 24end
25local _anon_func_8 = function(_arg_0, ...)
26 local ok = _arg_0
27 return ...
28end
29local _anon_func_10 = function(_arg_0, ...)
30 local _ok_0 = _arg_0
31 if _ok_0 then
32 return ...
33 end
34end
35local _anon_func_9 = function(func, pcall)
36 return _anon_func_10(pcall(func))
37end
38local _anon_func_12 = function(_arg_0, ...)
39 local _ok_0 = _arg_0
40 if _ok_0 then
41 return ...
42 end
43end
44local _anon_func_11 = function(func, pcall)
45 return _anon_func_12(pcall(func))
46end
47local _anon_func_14 = function(_arg_0, ...)
48 local _ok_0 = _arg_0
49 if _ok_0 then
50 return ...
51 end
52end
53local _anon_func_15 = function(func, print)
54 print(123)
55 return func()
56end
57local _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))
62end
25local f 63local f
26f = function() 64f = 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
113end 194end
195local _anon_func_16 = function(a, b, c, tb)
196 return tb.f(a, b, c)
197end
198local _anon_func_17 = function(_arg_0, ...)
199 local ok = _arg_0
200 return ...
201end
202do
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
376end
377return 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
44end 44end
45local _anon_func_0 = function(_u6253_u5370) 45local _anon_func_0 = function(_u6253_u5370)
46 do 46 _u6253_u5370(123)
47 _u6253_u5370(123) 47 return { }
48 return { }
49 end
50end 48end
51return __u65e0_u6548_u53d8_u91cf(function() 49return __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
243do 243do
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
254do 257do
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}
232local _max_0 = -5 232local _max_0 = #_u53d8_u91cfx + -5 + 1
233for _index_0 = 2, _max_0 < 0 and #_u53d8_u91cfx + _max_0 or _max_0, 2 do 233for _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)
236end 236end
237local _max_1 = 3 237for _index_0 = 1, 3 do
238for _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)
241end 240end
242for _index_0 = 2, #_u53d8_u91cfx do 241local _max_1 = #_u53d8_u91cfx
242for _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)
245end 245end
246for _index_0 = 1, #_u53d8_u91cfx, 2 do 246local _max_2 = #_u53d8_u91cfx
247for _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)
249end 250end
250for _index_0 = 2, #_u53d8_u91cfx, 2 do 251local _max_3 = #_u53d8_u91cfx
252for _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)
253end 255end
254local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2 256local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2
255local _max_2 = _u53d8_u91cfb 257local _min_0 = _u53d8_u91cfa
256for _index_0 = _u53d8_u91cfa, _max_2 < 0 and #_u53d8_u91cfx + _max_2 or _max_2, _u53d8_u91cfc do 258local _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
261for _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)
259end 264end
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
67end 67end
@@ -132,13 +132,11 @@ do
132end 132end
133do 133do
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
144end 142end
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
216end 216end
217local _ = require('δΈ‹εˆ’ηΊΏ') 217local _ = require('δΈ‹εˆ’ηΊΏ')
218local _anon_func_0 = function(_) 218local _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
230end 228end
231local _call_0 = ((function() 229local _call_0 = ((function()
232 local _call_0 = ((function() 230 local _call_0 = ((function()
@@ -241,17 +239,15 @@ local _call_0 = ((function()
241end)()) 239end)())
242local _u7ed3_u679ca = _call_0["取值"](_call_0) 240local _u7ed3_u679ca = _call_0["取值"](_call_0)
243local _anon_func_1 = function(_) 241local _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
255end 251end
256do 252do
257 local _call_1 = ((function() 253 local _call_1 = ((function()
@@ -270,10 +266,8 @@ do
270 end) 266 end)
271end 267end
272local _anon_func_2 = function(_u539f_u70b9) 268local _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
277end 271end
278local _call_1 = ((function() 272local _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
374end 366end
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
60end 60end
61local _anon_func_0 = function(_u53d8_u91cfa) 61local _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
66end 64end
67local _u51fd_u65701 65local _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
288local _anon_func_0 = function(_u4ec0_u4e48) 288local _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
293end 291end
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
126end 126end
127local _anon_func_12 = function(_u51fd_u6570) 127local _anon_func_12 = function(_u51fd_u6570)
128 do 128 return _u51fd_u6570()
129 return _u51fd_u6570()
130 end
131end 129end
132local _anon_func_13 = function(_u51fd_u6570, ...) 130local _anon_func_13 = function(_u51fd_u6570, ...)
133 do 131 return _u51fd_u6570(...)
134 return _u51fd_u6570(...)
135 end
136end 132end
137local _anon_func_14 = function(_u51fd_u6570) 133local _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
196end 192end
197local _anon_func_24 = function(_u6253_u5370, select, ...) 193local _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
202end 196end
203local _anon_func_25 = function(_u6253_u5370, ...) 197local _anon_func_25 = function(_u6253_u5370, ...)
204 do 198 return _u6253_u5370(...)
205 return _u6253_u5370(...)
206 end
207end 199end
208local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) 200local _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
215end 207end
216local _anon_func_27 = function(_u6253_u5370, ...) 208local _anon_func_27 = function(_u6253_u5370, ...)
217 do 209 return _u6253_u5370(...)
218 return _u6253_u5370(...)
219 end
220end 210end
221local _anon_func_28 = function(_u6761_u4ef6) 211local _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
225end 215end
226local _anon_func_29 = function(_u6253_u5370, _arg_0, ...) 216local _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
231end 219end
232local _u8fde_u63a5 220local _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
215end 215end
216local _anon_func_2 = function(print, select, _arg_0, ...) 216local _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
221end 219end
222local _anon_func_3 = function(tb) 220local _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")
243end 241end
244local _anon_func_6 = function(tb) 242local _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
250end 246end
251local _anon_func_7 = function(itemA, listA) 247local _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
355end 351end
356local _anon_func_17 = function(print) 352local _anon_func_17 = function(print)
357 do 353 print(123)
358 print(123) 354 return "abc"
359 return "abc"
360 end
361end 355end
362local _anon_func_18 = function(print, select, _arg_0, ...) 356local _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
369end 361end
370local _anon_func_19 = function(cond, i) 362local _anon_func_19 = function(cond, i)
@@ -459,11 +451,9 @@ local _anon_func_25 = function(itemA, listA)
459 return false 451 return false
460end 452end
461local _anon_func_24 = function(itemA, listA, tb) 453local _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
467end 457end
468GameEngine:onEvent("SomeEvent", function() 458GameEngine: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
504end 494end
505local _anon_func_28 = function(os, _arg_0, ...) 495local _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
514end 502end
515local _anon_func_29 = function(debug_env_after, debug_env_before, env, func) 503local _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
126end 126end
127local _anon_func_12 = function(func) 127local _anon_func_12 = function(func)
128 do 128 return func()
129 return func()
130 end
131end 129end
132local _anon_func_13 = function(func, ...) 130local _anon_func_13 = function(func, ...)
133 do 131 return func(...)
134 return func(...)
135 end
136end 132end
137local _anon_func_14 = function(func) 133local _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
196end 192end
197local _anon_func_24 = function(print, select, ...) 193local _anon_func_24 = function(print, select, ...)
198 do 194 print(select("#", ...))
199 print(select("#", ...)) 195 return print(...)
200 return print(...)
201 end
202end 196end
203local _anon_func_25 = function(print, ...) 197local _anon_func_25 = function(print, ...)
204 do 198 return print(...)
205 return print(...)
206 end
207end 199end
208local _anon_func_26 = function(tb, tb2, x) 200local _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
215end 207end
216local _anon_func_27 = function(print, ...) 208local _anon_func_27 = function(print, ...)
217 do 209 return print(...)
218 return print(...)
219 end
220end 210end
221local _anon_func_28 = function(cond) 211local _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
225end 215end
226local _anon_func_29 = function(print, _arg_0, ...) 216local _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
231end 219end
232local join 220local join
233join = function(...) 221join = 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
189end 189end
190do
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
235end
236do
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
251end
190return nil 252return 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
27WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, 27WatchID 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 {
167std::string TableAppendingOp_t::to_string(void*) const { 167std::string TableAppendingOp_t::to_string(void*) const {
168 return "[]"s; 168 return "[]"s;
169} 169}
170std::string PlainItem_t::to_string(void *) const { 170std::string PlainItem_t::to_string(void*) const {
171 return {}; 171 return {};
172} 172}
173std::string GlobalOp_t::to_string(void* ud) const { 173std::string GlobalOp_t::to_string(void*) const {
174 auto info = reinterpret_cast<YueFormat*>(ud); 174 return "*"s;
175 return info->convert(this);
176} 175}
177std::string ExportDefault_t::to_string(void*) const { 176std::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 {
188std::string NotIn_t::to_string(void*) const { 187std::string NotIn_t::to_string(void*) const {
189 return {}; 188 return {};
190} 189}
190std::string Break_t::to_string(void*) const {
191 return "break"s;
192}
193std::string Continue_t::to_string(void*) const {
194 return "continue"s;
195}
191std::string BreakLoop_t::to_string(void* ud) const { 196std::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}
195std::string YueLineComment_t::to_string(void* ud) const { 202std::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}
307std::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}
300std::string Import_t::to_string(void* ud) const { 318std::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}
345std::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}
327std::string PipeBody_t::to_string(void* ud) const { 351std::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 {
406std::string Switch_t::to_string(void* ud) const { 430std::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}
512std::string Repeat_t::to_string(void* ud) const { 573std::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}
529std::string ForStepValue_t::to_string(void* ud) const { 590std::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 {
596std::string Try_t::to_string(void* ud) const { 657std::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}
918std::string ReversedIndex_t::to_string(void* ud) const {
919 if (modifier) {
920 return "[# - "s + modifier->to_string(ud) + ']';
921 }
922 return "[#]"s;
923}
854std::string Callable_t::to_string(void* ud) const { 924std::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}
1010std::string YAMLIndent_t::to_string(void* ud) const {
1011 auto info = reinterpret_cast<YueFormat*>(ud);
1012 return info->convert(this);
1013}
1014std::string YAMLLineInner_t::to_string(void* ud) const {
1015 auto info = reinterpret_cast<YueFormat*>(ud);
1016 return info->convert(this);
1017}
1018std::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}
1024std::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}
1031std::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}
940std::string String_t::to_string(void* ud) const { 1055std::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}
1127std::string GlobalValues_t::to_string(void* ud) const { 1242std::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}
1138std::string Global_t::to_string(void* ud) const { 1253std::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}
1141std::string Export_t::to_string(void* ud) const { 1256std::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)
234AST_END(ImportAs) 234AST_END(ImportAs)
235 235
236AST_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)
241AST_END(ImportGlobal)
242
236AST_NODE(Import) 243AST_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)
239AST_END(Import) 246AST_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;
276AST_END(ExpList) 285AST_END(ExpList)
277 286
278AST_NODE(Return) 287AST_NODE(Return)
@@ -285,9 +294,9 @@ AST_END(Return)
285AST_NODE(With) 294AST_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)
291AST_END(With) 300AST_END(With)
292 301
293AST_NODE(SwitchList) 302AST_NODE(SwitchList)
@@ -302,20 +311,21 @@ AST_NODE(SwitchCase)
302 AST_MEMBER(SwitchCase, &condition, &body) 311 AST_MEMBER(SwitchCase, &condition, &body)
303AST_END(SwitchCase) 312AST_END(SwitchCase)
304 313
314AST_NODE(Assignment)
315 ast_ptr<false, ExpList_t> expList;
316 ast_ptr<true, Assign_t> assign;
317 AST_MEMBER(Assignment, &expList, &assign)
318AST_END(Assignment)
319
305AST_NODE(Switch) 320AST_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)
311AST_END(Switch) 327AST_END(Switch)
312 328
313AST_NODE(Assignment)
314 ast_ptr<false, ExpList_t> expList;
315 ast_ptr<true, Assign_t> assign;
316 AST_MEMBER(Assignment, &expList, &assign)
317AST_END(Assignment)
318
319AST_NODE(IfCond) 329AST_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)
343AST_END(While) 353AST_END(While)
344 354
345AST_NODE(Repeat) 355AST_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)
349AST_END(Repeat) 359AST_END(Repeat)
@@ -381,9 +391,10 @@ AST_NODE(CatchBlock)
381AST_END(CatchBlock) 391AST_END(CatchBlock)
382 392
383AST_NODE(Try) 393AST_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)
387AST_END(Try) 398AST_END(Try)
388 399
389AST_NODE(Comprehension) 400AST_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)
588AST_END(DoubleString) 599AST_END(DoubleString)
589 600
601AST_LEAF(YAMLIndent)
602AST_END(YAMLIndent)
603
604AST_LEAF(YAMLLineInner)
605AST_END(YAMLLineInner)
606
607AST_NODE(YAMLLineContent)
608 ast_sel<true, YAMLLineInner_t, Exp_t> content;
609 AST_MEMBER(YAMLLineContent, &content)
610AST_END(YAMLLineContent)
611
612AST_NODE(YAMLLine)
613 ast_ptr<true, YAMLIndent_t> indent;
614 ast_list<true, YAMLLineContent_t> segments;
615 AST_MEMBER(YAMLLine, &indent, &segments)
616AST_END(YAMLLine)
617
618AST_NODE(YAMLMultiline)
619 ast_ptr<true, Seperator_t> sep;
620 ast_list<true, YAMLLine_t> lines;
621 AST_MEMBER(YAMLMultiline, &sep, &lines)
622AST_END(YAMLMultiline)
623
590AST_NODE(String) 624AST_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)
593AST_END(String) 627AST_END(String)
594 628
@@ -639,9 +673,14 @@ AST_END(TableAppendingOp)
639AST_LEAF(PlainItem) 673AST_LEAF(PlainItem)
640AST_END(PlainItem) 674AST_END(PlainItem)
641 675
676AST_NODE(ReversedIndex)
677 ast_ptr<false, Exp_t> modifier;
678 AST_MEMBER(ReversedIndex, &modifier)
679AST_END(ReversedIndex)
680
642AST_NODE(ChainValue) 681AST_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)
647AST_END(ChainValue) 686AST_END(ChainValue)
@@ -725,8 +764,9 @@ AST_LEAF(GlobalOp)
725AST_END(GlobalOp) 764AST_END(GlobalOp)
726 765
727AST_NODE(Global) 766AST_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)
730AST_END(Global) 770AST_END(Global)
731 771
732AST_LEAF(ExportDefault) 772AST_LEAF(ExportDefault)
@@ -742,15 +782,17 @@ AST_END(Export)
742AST_NODE(FnArgDef) 782AST_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)
747AST_END(FnArgDef) 788AST_END(FnArgDef)
748 789
749AST_NODE(FnArgDefList) 790AST_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)
754AST_END(FnArgDefList) 796AST_END(FnArgDefList)
755 797
756AST_NODE(OuterVarShadow) 798AST_NODE(OuterVarShadow)
@@ -838,9 +880,15 @@ AST_NODE(UnaryExp)
838 AST_MEMBER(UnaryExp, &ops, &expos, &inExp) 880 AST_MEMBER(UnaryExp, &ops, &expos, &inExp)
839AST_END(UnaryExp) 881AST_END(UnaryExp)
840 882
883AST_NODE(SubBackcall)
884 ast_ptr<true, FnArrowBack_t> arrow;
885 ast_ptr<true, ChainValue_t> value;
886 AST_MEMBER(SubBackcall, &arrow, &value)
887AST_END(SubBackcall)
888
841AST_NODE(ExpListAssign) 889AST_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)
845AST_END(ExpListAssign) 893AST_END(ExpListAssign)
846 894
@@ -856,7 +904,17 @@ AST_NODE(WhileLine)
856 AST_MEMBER(WhileLine, &type, &condition) 904 AST_MEMBER(WhileLine, &type, &condition)
857AST_END(WhileLine) 905AST_END(WhileLine)
858 906
859AST_LEAF(BreakLoop) 907AST_LEAF(Break)
908AST_END(Break)
909
910AST_LEAF(Continue)
911AST_END(Continue)
912
913AST_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;
860AST_END(BreakLoop) 918AST_END(BreakLoop)
861 919
862AST_NODE(PipeBody) 920AST_NODE(PipeBody)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 590c502..d676750 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = {
78 "close"s // Lua 5.4 78 "close"s // Lua 5.4
79}; 79};
80 80
81const std::string_view version = "0.27.5"sv; 81const std::string_view version = "0.29.3"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class CompileError : public std::logic_error {
@@ -165,12 +165,12 @@ public:
165 double compileTime = 0.0; 165 double compileTime = 0.0;
166 if (config.profiling) { 166 if (config.profiling) {
167 auto start = std::chrono::high_resolution_clock::now(); 167 auto start = std::chrono::high_resolution_clock::now();
168 _info = _parser.parse<File_t>(codes); 168 _info = _parser.parse<File_t>(codes, config.lax);
169 auto stop = std::chrono::high_resolution_clock::now(); 169 auto stop = std::chrono::high_resolution_clock::now();
170 std::chrono::duration<double> diff = stop - start; 170 std::chrono::duration<double> diff = stop - start;
171 parseTime = diff.count(); 171 parseTime = diff.count();
172 } else { 172 } else {
173 _info = _parser.parse<File_t>(codes); 173 _info = _parser.parse<File_t>(codes, config.lax);
174 } 174 }
175 std::unique_ptr<GlobalVars> globals; 175 std::unique_ptr<GlobalVars> globals;
176 std::unique_ptr<Options> options; 176 std::unique_ptr<Options> options;
@@ -429,8 +429,9 @@ private:
429 }; 429 };
430 enum class VarType { 430 enum class VarType {
431 Local = 0, 431 Local = 0,
432 Const = 1, 432 LocalConst = 1,
433 Global = 2 433 Global = 2,
434 GlobalConst = 3
434 }; 435 };
435 struct Scope { 436 struct Scope {
436 GlobalMode mode = GlobalMode::None; 437 GlobalMode mode = GlobalMode::None;
@@ -558,7 +559,7 @@ private:
558 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { 559 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) {
559 auto vars = it->vars.get(); 560 auto vars = it->vars.get();
560 auto vit = vars->find(name); 561 auto vit = vars->find(name);
561 if (vit != vars->end() && vit->second != VarType::Global) { 562 if (vit != vars->end() && (vit->second == VarType::Local || vit->second == VarType::LocalConst)) {
562 local = true; 563 local = true;
563 break; 564 break;
564 } 565 }
@@ -571,7 +572,7 @@ private:
571 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { 572 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) {
572 auto vars = it->vars.get(); 573 auto vars = it->vars.get();
573 auto vit = vars->find(name); 574 auto vit = vars->find(name);
574 if (vit != vars->end() && vit->second == VarType::Global) { 575 if (vit != vars->end() && (vit->second == VarType::Global || vit->second == VarType::GlobalConst)) {
575 global = true; 576 global = true;
576 break; 577 break;
577 } 578 }
@@ -593,7 +594,7 @@ private:
593 auto vars = it->vars.get(); 594 auto vars = it->vars.get();
594 auto vit = vars->find(name); 595 auto vit = vars->find(name);
595 if (vit != vars->end()) { 596 if (vit != vars->end()) {
596 isConst = (vit->second == VarType::Const); 597 isConst = (vit->second == VarType::LocalConst || vit->second == VarType::GlobalConst);
597 break; 598 break;
598 } 599 }
599 if (checkShadowScopeOnly && it->allows) break; 600 if (checkShadowScopeOnly && it->allows) break;
@@ -874,9 +875,9 @@ private:
874 return false; 875 return false;
875 } 876 }
876 877
877 void markVarConst(const std::string& name) { 878 void markVarLocalConst(const std::string& name) {
878 auto& scope = _scopes.back(); 879 auto& scope = _scopes.back();
879 scope.vars->insert_or_assign(name, VarType::Const); 880 scope.vars->insert_or_assign(name, VarType::LocalConst);
880 } 881 }
881 882
882 void markVarShadowed() { 883 void markVarShadowed() {
@@ -895,6 +896,11 @@ private:
895 scope.vars->insert_or_assign(name, VarType::Global); 896 scope.vars->insert_or_assign(name, VarType::Global);
896 } 897 }
897 898
899 void markVarGlobalConst(const std::string& name) {
900 auto& scope = _scopes.back();
901 scope.vars->insert_or_assign(name, VarType::GlobalConst);
902 }
903
898 void addToAllowList(const std::string& name) { 904 void addToAllowList(const std::string& name) {
899 auto& scope = _scopes.back(); 905 auto& scope = _scopes.back();
900 scope.allows->insert(name); 906 scope.allows->insert(name);
@@ -1252,7 +1258,7 @@ private:
1252 1258
1253 template <class T> 1259 template <class T>
1254 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) {
1255 auto res = _parser.parse<T>(std::string(codes)); 1261 auto res = _parser.parse<T>(std::string(codes), false);
1256 if (res.error) { 1262 if (res.error) {
1257 throw CompileError(res.error.value().msg, parent); 1263 throw CompileError(res.error.value().msg, parent);
1258 } 1264 }
@@ -1275,6 +1281,8 @@ private:
1275 Common, 1281 Common,
1276 EndWithColon, 1282 EndWithColon,
1277 EndWithEOP, 1283 EndWithEOP,
1284 EndWithSlice,
1285 HasRIndex,
1278 HasEOP, 1286 HasEOP,
1279 HasKeyword, 1287 HasKeyword,
1280 HasUnicode, 1288 HasUnicode,
@@ -1293,6 +1301,9 @@ private:
1293 if (ast_is<ExistentialOp_t>(chainValue->items.back())) { 1301 if (ast_is<ExistentialOp_t>(chainValue->items.back())) {
1294 return ChainType::EndWithEOP; 1302 return ChainType::EndWithEOP;
1295 } 1303 }
1304 if (ast_is<Slice_t>(chainValue->items.back())) {
1305 return ChainType::EndWithSlice;
1306 }
1296 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { 1307 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) {
1297 if (dot->name.is<Metatable_t>()) { 1308 if (dot->name.is<Metatable_t>()) {
1298 return ChainType::Metatable; 1309 return ChainType::Metatable;
@@ -1318,6 +1329,8 @@ private:
1318 } 1329 }
1319 } else if (ast_is<ExistentialOp_t>(item)) { 1330 } else if (ast_is<ExistentialOp_t>(item)) {
1320 return ChainType::HasEOP; 1331 return ChainType::HasEOP;
1332 } else if (ast_is<ReversedIndex_t>(item)) {
1333 return ChainType::HasRIndex;
1321 } 1334 }
1322 } 1335 }
1323 return type; 1336 return type;
@@ -1840,6 +1853,7 @@ private:
1840 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;
1841 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;
1842 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;
1843 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;
1844 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;
1845 case id<Comprehension_t>(): { 1859 case id<Comprehension_t>(): {
@@ -2051,13 +2065,16 @@ private:
2051 if (item.targetVar.empty()) { 2065 if (item.targetVar.empty()) {
2052 throw CompileError("can only declare variable as const"sv, item.target); 2066 throw CompileError("can only declare variable as const"sv, item.target);
2053 } 2067 }
2054 markVarConst(item.targetVar); 2068 markVarLocalConst(item.targetVar);
2055 } 2069 }
2056 } 2070 }
2057 } 2071 }
2058 } 2072 }
2059 2073
2060 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 }
2061 checkAssignable(assignment->expList); 2078 checkAssignable(assignment->expList);
2062 BLOCK_START 2079 BLOCK_START
2063 auto assign = ast_cast<Assign_t>(assignment->action); 2080 auto assign = ast_cast<Assign_t>(assignment->action);
@@ -2320,6 +2337,17 @@ private:
2320 out.back().insert(0, preDefine); 2337 out.back().insert(0, preDefine);
2321 return false; 2338 return false;
2322 } 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 }
2323 case id<Switch_t>(): { 2351 case id<Switch_t>(): {
2324 auto switchNode = static_cast<Switch_t*>(value); 2352 auto switchNode = static_cast<Switch_t*>(value);
2325 auto assignList = assignment->expList.get(); 2353 auto assignList = assignment->expList.get();
@@ -2391,6 +2419,13 @@ private:
2391 out.back().insert(0, preDefine); 2419 out.back().insert(0, preDefine);
2392 return false; 2420 return false;
2393 } 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 }
2394 case id<TableLit_t>(): { 2429 case id<TableLit_t>(): {
2395 auto tableLit = static_cast<TableLit_t*>(value); 2430 auto tableLit = static_cast<TableLit_t*>(value);
2396 if (hasSpreadExp(tableLit->values.objects())) { 2431 if (hasSpreadExp(tableLit->values.objects())) {
@@ -2443,12 +2478,14 @@ private:
2443 switch (type) { 2478 switch (type) {
2444 case ChainType::HasEOP: 2479 case ChainType::HasEOP:
2445 case ChainType::EndWithColon: 2480 case ChainType::EndWithColon:
2481 case ChainType::EndWithSlice:
2446 case ChainType::MetaFieldInvocation: { 2482 case ChainType::MetaFieldInvocation: {
2447 std::string preDefine = getPreDefineLine(assignment); 2483 std::string preDefine = getPreDefineLine(assignment);
2448 transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); 2484 transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct);
2449 out.back().insert(0, preDefine); 2485 out.back().insert(0, preDefine);
2450 return false; 2486 return false;
2451 } 2487 }
2488 case ChainType::HasRIndex:
2452 case ChainType::HasKeyword: 2489 case ChainType::HasKeyword:
2453 case ChainType::HasUnicode: 2490 case ChainType::HasUnicode:
2454 case ChainType::Macro: 2491 case ChainType::Macro:
@@ -2464,6 +2501,10 @@ private:
2464 auto info = extractDestructureInfo(assignment, false, optionalDestruct); 2501 auto info = extractDestructureInfo(assignment, false, optionalDestruct);
2465 if (info.destructures.empty()) { 2502 if (info.destructures.empty()) {
2466 transformAssignmentCommon(assignment, out); 2503 transformAssignmentCommon(assignment, out);
2504 if (assignment->expList->followStmt) {
2505 transformStatement(assignment->expList->followStmt, out);
2506 assignment->expList->followStmtProcessed = true;
2507 }
2467 return true; 2508 return true;
2468 } else { 2509 } else {
2469 auto x = assignment; 2510 auto x = assignment;
@@ -2729,8 +2770,12 @@ private:
2729 temp.push_back(indent() + "end"s + nlr(x)); 2770 temp.push_back(indent() + "end"s + nlr(x));
2730 } 2771 }
2731 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;
2732 } 2778 }
2733 return false;
2734 } 2779 }
2735 2780
2736 void transformAssignItem(ast_node* value, str_list& out) { 2781 void transformAssignItem(ast_node* value, str_list& out) {
@@ -2796,20 +2841,46 @@ private:
2796 if (!tableItems) throw CompileError("invalid destructure value"sv, node); 2841 if (!tableItems) throw CompileError("invalid destructure value"sv, node);
2797 std::list<DestructItem> pairs; 2842 std::list<DestructItem> pairs;
2798 int index = 0; 2843 int index = 0;
2844 int count = 0;
2845 bool hasSpread = false;
2799 auto subMetaDestruct = node->new_ptr<TableLit_t>(); 2846 auto subMetaDestruct = node->new_ptr<TableLit_t>();
2800 for (auto pair : *tableItems) { 2847 for (auto pair : *tableItems) {
2801 switch (pair->get_id()) { 2848 switch (pair->get_id()) {
2802 case id<Exp_t>(): 2849 case id<Exp_t>():
2803 case id<NormalDef_t>(): { 2850 case id<NormalDef_t>(): {
2851 ++index;
2804 Exp_t* defVal = nullptr; 2852 Exp_t* defVal = nullptr;
2805 if (auto nd = ast_cast<NormalDef_t>(pair)) { 2853 if (auto nd = ast_cast<NormalDef_t>(pair)) {
2806 pair = nd->item.get(); 2854 pair = nd->item.get();
2807 defVal = nd->defVal.get(); 2855 defVal = nd->defVal.get();
2808 } 2856 }
2809 ++index; 2857 bool assignable = false;
2810 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;
2811 throw CompileError("can't destructure value"sv, pair); 2865 throw CompileError("can't destructure value"sv, pair);
2812 } 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 }
2813 auto value = singleValueFrom(pair); 2884 auto value = singleValueFrom(pair);
2814 auto item = value->item.get(); 2885 auto item = value->item.get();
2815 ast_node* subExp = ast_cast<SimpleTable_t>(item); 2886 ast_node* subExp = ast_cast<SimpleTable_t>(item);
@@ -2820,7 +2891,6 @@ private:
2820 throw CompileError("default value is not supported here"sv, defVal); 2891 throw CompileError("default value is not supported here"sv, defVal);
2821 } 2892 }
2822 } 2893 }
2823 auto indexItem = toAst<Exp_t>(std::to_string(index), value);
2824 for (auto& p : subPairs) { 2894 for (auto& p : subPairs) {
2825 if (sep) p.structure->items.push_front(sep); 2895 if (sep) p.structure->items.push_front(sep);
2826 p.structure->items.push_front(indexItem); 2896 p.structure->items.push_front(indexItem);
@@ -2831,7 +2901,6 @@ private:
2831 auto varName = singleVariableFrom(exp, AccessType::None); 2901 auto varName = singleVariableFrom(exp, AccessType::None);
2832 if (varName == "_"sv) break; 2902 if (varName == "_"sv) break;
2833 auto chain = exp->new_ptr<ChainValue_t>(); 2903 auto chain = exp->new_ptr<ChainValue_t>();
2834 auto indexItem = toAst<Exp_t>(std::to_string(index), exp);
2835 chain->items.push_back(indexItem); 2904 chain->items.push_back(indexItem);
2836 pairs.push_back({exp, 2905 pairs.push_back({exp,
2837 varName, 2906 varName,
@@ -2889,7 +2958,25 @@ private:
2889 } 2958 }
2890 } 2959 }
2891 if (auto exp = np->value.as<Exp_t>()) { 2960 if (auto exp = np->value.as<Exp_t>()) {
2892 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 }
2893 auto item = singleValueFrom(exp)->item.get(); 2980 auto item = singleValueFrom(exp)->item.get();
2894 ast_node* subExp = ast_cast<SimpleTable_t>(item); 2981 ast_node* subExp = ast_cast<SimpleTable_t>(item);
2895 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>())) {
@@ -2938,7 +3025,13 @@ private:
2938 auto tb = static_cast<TableBlockIndent_t*>(pair); 3025 auto tb = static_cast<TableBlockIndent_t*>(pair);
2939 ++index; 3026 ++index;
2940 auto subPairs = destructFromExp(tb, varDefOnly, optional); 3027 auto subPairs = destructFromExp(tb, varDefOnly, optional);
2941 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 }
2942 for (auto& p : subPairs) { 3035 for (auto& p : subPairs) {
2943 if (sep) p.structure->items.push_front(sep); 3036 if (sep) p.structure->items.push_front(sep);
2944 p.structure->items.push_front(indexItem); 3037 p.structure->items.push_front(indexItem);
@@ -2995,6 +3088,42 @@ private:
2995 subMetaDestruct->values.push_back(newPairDef); 3088 subMetaDestruct->values.push_back(newPairDef);
2996 break; 3089 break;
2997 } 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 }
2998 default: YUEE("AST node mismatch", pair); break; 3127 default: YUEE("AST node mismatch", pair); break;
2999 } 3128 }
3000 } 3129 }
@@ -3111,7 +3240,11 @@ private:
3111 break; 3240 break;
3112 default: YUEE("AST node mismatch", destructNode); break; 3241 default: YUEE("AST node mismatch", destructNode); break;
3113 } 3242 }
3114 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 }
3115 for (auto item : *dlist) { 3248 for (auto item : *dlist) {
3116 switch (item->get_id()) { 3249 switch (item->get_id()) {
3117 case id<MetaVariablePairDef_t>(): { 3250 case id<MetaVariablePairDef_t>(): {
@@ -3247,7 +3380,9 @@ private:
3247 simpleValue->value.set(tab); 3380 simpleValue->value.set(tab);
3248 auto pairs = destructFromExp(newExp(simpleValue, expr), varDefOnly, optional); 3381 auto pairs = destructFromExp(newExp(simpleValue, expr), varDefOnly, optional);
3249 if (pairs.empty()) { 3382 if (pairs.empty()) {
3250 throw CompileError("expect items to be destructured"sv, tab); 3383 if (!optional) {
3384 throw CompileError("expect items to be destructured"sv, tab);
3385 }
3251 } 3386 }
3252 destruct.items = std::move(pairs); 3387 destruct.items = std::move(pairs);
3253 if (!varDefOnly) { 3388 if (!varDefOnly) {
@@ -3286,7 +3421,7 @@ private:
3286 destruct.valueVar.clear(); 3421 destruct.valueVar.clear();
3287 } 3422 }
3288 } 3423 }
3289 destructs.push_back(destruct); 3424 destructs.push_back(std::move(destruct));
3290 } 3425 }
3291 } 3426 }
3292 } else { 3427 } else {
@@ -4205,12 +4340,22 @@ private:
4205 4340
4206 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) {
4207 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 }
4208 auto returnNode = exp->new_ptr<Return_t>(); 4354 auto returnNode = exp->new_ptr<Return_t>();
4209 returnNode->explicitReturn = false; 4355 returnNode->explicitReturn = false;
4210 auto returnList = exp->new_ptr<ExpListLow_t>(); 4356 auto returnList = exp->new_ptr<ExpListLow_t>();
4211 returnList->exprs.push_back(exp); 4357 returnList->exprs.push_back(exp);
4212 returnNode->valueList.set(returnList); 4358 returnNode->valueList.set(returnList);
4213 auto block = exp->new_ptr<Block_t>();
4214 auto stmt = exp->new_ptr<Statement_t>(); 4359 auto stmt = exp->new_ptr<Statement_t>();
4215 stmt->content.set(returnNode); 4360 stmt->content.set(returnNode);
4216 block->statements.push_back(stmt); 4361 block->statements.push_back(stmt);
@@ -4287,7 +4432,9 @@ private:
4287 return false; 4432 return false;
4288 }; 4433 };
4289 switch (usage) { 4434 switch (usage) {
4290 case ExpUsage::Common: YUEE("AST node mismatch", x); return; 4435 case ExpUsage::Common:
4436 YUEE("AST node mismatch", x);
4437 return;
4291 case ExpUsage::Return: 4438 case ExpUsage::Return:
4292 case ExpUsage::Closure: { 4439 case ExpUsage::Closure: {
4293 prepareValue(); 4440 prepareValue();
@@ -4410,6 +4557,7 @@ private:
4410 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;
4411 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;
4412 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;
4413 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;
4414 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;
4415 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;
@@ -4729,11 +4877,7 @@ private:
4729 auto newBody = x->new_ptr<Body_t>(); 4877 auto newBody = x->new_ptr<Body_t>();
4730 newBody->content.set(followingBlock); 4878 newBody->content.set(followingBlock);
4731 { 4879 {
4732 auto doNode = x->new_ptr<Do_t>(); 4880 if (auto result = upValueFuncFromBlock(followingBlock.get(), &argNames, false, true)) {
4733 doNode->body.set(newBody);
4734 auto simpleValue = x->new_ptr<SimpleValue_t>();
4735 simpleValue->value.set(doNode);
4736 if (auto result = upValueFuncFromExp(newExp(simpleValue, x), &argNames, true)) {
4737 auto [funcName, args] = std::move(*result); 4881 auto [funcName, args] = std::move(*result);
4738 str_list finalArgs; 4882 str_list finalArgs;
4739 for (const auto& arg : args) { 4883 for (const auto& arg : args) {
@@ -4741,9 +4885,13 @@ private:
4741 finalArgs.push_back(arg); 4885 finalArgs.push_back(arg);
4742 } 4886 }
4743 } 4887 }
4744 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));
4745 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);
4746 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);
4747 transformBlock(newBlock, out, usage, assignList, isRoot); 4895 transformBlock(newBlock, out, usage, assignList, isRoot);
4748 return; 4896 return;
4749 } 4897 }
@@ -4820,6 +4968,38 @@ private:
4820 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));
4821 transformBlock(newBlock, out, usage, assignList, isRoot); 4969 transformBlock(newBlock, out, usage, assignList, isRoot);
4822 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;
4823 } 5003 }
4824 if (auto local = stmt->content.as<Local_t>()) { 5004 if (auto local = stmt->content.as<Local_t>()) {
4825 if (!local->collected) { 5005 if (!local->collected) {
@@ -4991,36 +5171,45 @@ private:
4991 if (!nodes.empty()) { 5171 if (!nodes.empty()) {
4992 str_list temp; 5172 str_list temp;
4993 for (auto node : nodes) { 5173 for (auto node : nodes) {
4994 currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None; 5174 auto transformNode = [&]() {
4995 transformStatement(static_cast<Statement_t*>(node), temp); 5175 currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None;
4996 if (isRoot && !_rootDefs.empty()) { 5176 transformStatement(static_cast<Statement_t*>(node), temp);
4997 auto last = std::move(temp.back()); 5177 if (isRoot && !_rootDefs.empty()) {
4998 temp.pop_back(); 5178 auto last = std::move(temp.back());
4999 temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); 5179 temp.pop_back();
5000 _rootDefs.clear(); 5180 temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end());
5001 temp.push_back(std::move(last)); 5181 _rootDefs.clear();
5002 } 5182 temp.push_back(std::move(last));
5003 if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { 5183 }
5004 auto rit = ++temp.rbegin(); 5184 if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) {
5005 if (rit != temp.rend() && !rit->empty()) { 5185 auto rit = ++temp.rbegin();
5006 auto index = std::string::npos; 5186 if (rit != temp.rend() && !rit->empty()) {
5007 if (_config.reserveLineNumber) { 5187 auto index = std::string::npos;
5008 index = rit->rfind(" -- "sv); 5188 if (_config.reserveLineNumber) {
5009 } else { 5189 index = rit->rfind(" -- "sv);
5010 index = rit->find_last_not_of('\n'); 5190 } else {
5011 if (index != std::string::npos) index++; 5191 index = rit->find_last_not_of('\n');
5012 } 5192 if (index != std::string::npos) index++;
5013 if (index != std::string::npos) {
5014 auto ending = rit->substr(0, index);
5015 auto ind = ending.find_last_of(" \t\n"sv);
5016 if (ind != std::string::npos) {
5017 ending = ending.substr(ind + 1);
5018 } 5193 }
5019 if (LuaKeywords.find(ending) == LuaKeywords.end()) { 5194 if (index != std::string::npos) {
5020 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 }
5021 } 5203 }
5022 } 5204 }
5023 } 5205 }
5206 };
5207 if (_config.lax) {
5208 try {
5209 transformNode();
5210 } catch (const CompileError&) { }
5211 } else {
5212 transformNode();
5024 } 5213 }
5025 } 5214 }
5026 out.push_back(join(temp)); 5215 out.push_back(join(temp));
@@ -5229,18 +5418,29 @@ private:
5229 auto macroLit = macro->decl.to<MacroLit_t>(); 5418 auto macroLit = macro->decl.to<MacroLit_t>();
5230 auto argsDef = macroLit->argsDef.get(); 5419 auto argsDef = macroLit->argsDef.get();
5231 str_list newArgs; 5420 str_list newArgs;
5421 str_list argChecks;
5422 bool hasCheck = false;
5232 if (argsDef) { 5423 if (argsDef) {
5233 for (auto def_ : argsDef->definitions.objects()) { 5424 for (auto def_ : argsDef->definitions.objects()) {
5234 auto def = static_cast<FnArgDef_t*>(def_); 5425 auto def = static_cast<FnArgDef_t*>(def_);
5235 if (def->name.is<SelfItem_t>()) { 5426 if (def->name.is<SelfItem_t>()) {
5236 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);
5237 } 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 }
5238 std::string defVal; 5439 std::string defVal;
5239 if (def->defaultValue) { 5440 if (def->defaultValue) {
5240 defVal = _parser.toString(def->defaultValue); 5441 defVal = _parser.toString(def->defaultValue);
5241 Utils::trim(defVal); 5442 Utils::trim(defVal);
5242 defVal.insert(0, "=[==========["sv); 5443 defVal = '=' + Utils::toLuaDoubleString(defVal);
5243 defVal.append("]==========]"sv);
5244 } 5444 }
5245 newArgs.emplace_back(_parser.toString(def->name) + defVal); 5445 newArgs.emplace_back(_parser.toString(def->name) + defVal);
5246 } 5446 }
@@ -5248,6 +5448,14 @@ private:
5248 if (argsDef->varArg) { 5448 if (argsDef->varArg) {
5249 newArgs.emplace_back(_parser.toString(argsDef->varArg)); 5449 newArgs.emplace_back(_parser.toString(argsDef->varArg));
5250 } 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 }
5251 } 5459 }
5252 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);
5253 auto chunkName = "=(macro "s + macroName + ')'; 5461 auto chunkName = "=(macro "s + macroName + ')';
@@ -5278,6 +5486,24 @@ private:
5278 throw CompileError("failed to generate macro function\n"s + err, macroLit); 5486 throw CompileError("failed to generate macro function\n"s + err, macroLit);
5279 } // cur true macro 5487 } // cur true macro
5280 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
5281 if (exporting && _config.exporting && !_config.module.empty()) { 5507 if (exporting && _config.exporting && !_config.module.empty()) {
5282 pushModuleTable(_config.module); // cur macro module 5508 pushModuleTable(_config.module); // cur macro module
5283 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
@@ -5352,6 +5578,9 @@ private:
5352 case id<While_t>(): 5578 case id<While_t>():
5353 transformWhileInPlace(static_cast<While_t*>(value), out); 5579 transformWhileInPlace(static_cast<While_t*>(value), out);
5354 return; 5580 return;
5581 case id<Repeat_t>():
5582 transformRepeatInPlace(static_cast<Repeat_t*>(value), out);
5583 return;
5355 case id<For_t>(): 5584 case id<For_t>():
5356 transformForInPlace(static_cast<For_t*>(value), out); 5585 transformForInPlace(static_cast<For_t*>(value), out);
5357 return; 5586 return;
@@ -5432,7 +5661,11 @@ private:
5432 auto def = static_cast<FnArgDef_t*>(_def); 5661 auto def = static_cast<FnArgDef_t*>(_def);
5433 auto& arg = argItems.emplace_back(); 5662 auto& arg = argItems.emplace_back();
5434 switch (def->name->get_id()) { 5663 switch (def->name->get_id()) {
5435 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 }
5436 case id<SelfItem_t>(): { 5669 case id<SelfItem_t>(): {
5437 assignSelf = true; 5670 assignSelf = true;
5438 if (def->op) { 5671 if (def->op) {
@@ -5571,6 +5804,45 @@ private:
5571 } 5804 }
5572 } 5805 }
5573 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
5574 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) {
5575 auto x = chainList.front(); 5847 auto x = chainList.front();
5576 if (ast_is<ExistentialOp_t>(chainList.back())) { 5848 if (ast_is<ExistentialOp_t>(chainList.back())) {
@@ -6088,7 +6360,7 @@ private:
6088 case id<ColonChainItem_t>(): 6360 case id<ColonChainItem_t>():
6089 case id<Exp_t>(): 6361 case id<Exp_t>():
6090 if (_withVars.empty()) { 6362 if (_withVars.empty()) {
6091 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);
6092 } else { 6364 } else {
6093 temp.push_back(_withVars.top()); 6365 temp.push_back(_withVars.top());
6094 } 6366 }
@@ -6234,6 +6506,93 @@ private:
6234 } 6506 }
6235 return; 6507 return;
6236 } 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;
6237 } 6596 }
6238 } 6597 }
6239 } 6598 }
@@ -6418,7 +6777,7 @@ private:
6418 } 6777 }
6419 } 6778 }
6420 } 6779 }
6421 int len = lua_objlen(L, -1); 6780 int len = static_cast<int>(lua_objlen(L, -1));
6422 lua_pushnil(L); // cur nil 6781 lua_pushnil(L); // cur nil
6423 for (int i = len; i >= 1; i--) { 6782 for (int i = len; i >= 1; i--) {
6424 lua_pop(L, 1); // cur 6783 lua_pop(L, 1); // cur
@@ -6430,7 +6789,25 @@ private:
6430 break; 6789 break;
6431 } 6790 }
6432 } 6791 }
6433 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)) {
6434 auto code = expandBuiltinMacro(macroName, x); 6811 auto code = expandBuiltinMacro(macroName, x);
6435 if (!code.empty()) return code; 6812 if (!code.empty()) return code;
6436 if (macroName == "is_ast"sv) { 6813 if (macroName == "is_ast"sv) {
@@ -6475,11 +6852,34 @@ private:
6475 } // cur macroFunc 6852 } // cur macroFunc
6476 pushYue("pcall"sv); // cur macroFunc pcall 6853 pushYue("pcall"sv); // cur macroFunc pcall
6477 lua_insert(L, -2); // cur pcall macroFunc 6854 lua_insert(L, -2); // cur pcall macroFunc
6478 if (!lua_checkstack(L, argStrs.size())) { 6855 if (!lua_checkstack(L, static_cast<int>(argStrs.size()))) {
6479 throw CompileError("too much macro params"s, x); 6856 throw CompileError("too much macro params"s, x);
6480 } 6857 }
6858 auto checkIt = checks.begin();
6859 node_container::const_iterator argIt;
6860 if (args) {
6861 argIt = args->begin();
6862 }
6481 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 }
6482 lua_pushlstring(L, arg.c_str(), arg.size()); 6881 lua_pushlstring(L, arg.c_str(), arg.size());
6882 ++argIt;
6483 } // cur pcall macroFunc args... 6883 } // cur pcall macroFunc args...
6484 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;
6485 if (!success) { // cur err 6885 if (!success) { // cur err
@@ -6609,14 +7009,14 @@ private:
6609 } else { 7009 } else {
6610 if (!codes.empty()) { 7010 if (!codes.empty()) {
6611 if (isBlock) { 7011 if (isBlock) {
6612 info = _parser.parse<BlockEnd_t>(codes); 7012 info = _parser.parse<BlockEnd_t>(codes, false);
6613 if (info.error) { 7013 if (info.error) {
6614 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);
6615 } 7015 }
6616 } else { 7016 } else {
6617 info = _parser.parse<Exp_t>(codes); 7017 info = _parser.parse<Exp_t>(codes, false);
6618 if (!info.node && allowBlockMacroReturn) { 7018 if (!info.node && allowBlockMacroReturn) {
6619 info = _parser.parse<BlockEnd_t>(codes); 7019 info = _parser.parse<BlockEnd_t>(codes, false);
6620 if (info.error) { 7020 if (info.error) {
6621 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);
6622 } 7022 }
@@ -6752,6 +7152,9 @@ private:
6752 if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { 7152 if (transformChainEndWithColonItem(chainList, out, usage, assignList)) {
6753 return; 7153 return;
6754 } 7154 }
7155 if (transformChainEndWithSlice(chainList, out, usage, assignList)) {
7156 return;
7157 }
6755 transformChainList(chainList, out, usage, assignList); 7158 transformChainList(chainList, out, usage, assignList);
6756 } 7159 }
6757 7160
@@ -7153,7 +7556,7 @@ private:
7153 try { 7556 try {
7154 unsigned long long value = std::stoull(binaryPart, nullptr, 2); 7557 unsigned long long value = std::stoull(binaryPart, nullptr, 2);
7155 numStr = std::to_string(value); 7558 numStr = std::to_string(value);
7156 } catch (const std::exception& e) { 7559 } catch (const std::exception&) {
7157 throw CompileError("invalid binary literal"sv, num); 7560 throw CompileError("invalid binary literal"sv, num);
7158 } 7561 }
7159 } else if (getLuaTarget(num) < 502) { 7562 } else if (getLuaTarget(num) < 502) {
@@ -7859,6 +8262,11 @@ private:
7859 } 8262 }
7860 8263
7861 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 };
7862 auto x = nameList; 8270 auto x = nameList;
7863 str_list temp; 8271 str_list temp;
7864 str_list vars; 8272 str_list vars;
@@ -7925,15 +8333,35 @@ private:
7925 for (auto item : chainList) { 8333 for (auto item : chainList) {
7926 chain->items.push_back(item); 8334 chain->items.push_back(item);
7927 } 8335 }
7928 std::string startValue("1"sv); 8336 std::string startValue;
8337 NumState startStatus = NumState::Unknown;
7929 if (auto exp = slice->startValue.as<Exp_t>()) { 8338 if (auto exp = slice->startValue.as<Exp_t>()) {
7930 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 }
7931 startValue = std::move(temp.back()); 8349 startValue = std::move(temp.back());
7932 temp.pop_back(); 8350 temp.pop_back();
7933 } 8351 }
7934 std::string stopValue; 8352 std::string stopValue;
8353 NumState stopStatus = NumState::Unknown;
7935 if (auto exp = slice->stopValue.as<Exp_t>()) { 8354 if (auto exp = slice->stopValue.as<Exp_t>()) {
7936 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 }
7937 stopValue = std::move(temp.back()); 8365 stopValue = std::move(temp.back());
7938 temp.pop_back(); 8366 temp.pop_back();
7939 } 8367 }
@@ -7955,8 +8383,33 @@ private:
7955 transformChainValue(chain, temp, ExpUsage::Closure); 8383 transformChainValue(chain, temp, ExpUsage::Closure);
7956 _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); 8384 _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList);
7957 } 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 }
7958 std::string maxVar; 8411 std::string maxVar;
7959 if (!stopValue.empty()) { 8412 if (stopStatus != NumState::Positive) {
7960 std::string prefix; 8413 std::string prefix;
7961 if (!extraScope && !inClosure && needScope) { 8414 if (!extraScope && !inClosure && needScope) {
7962 extraScope = true; 8415 extraScope = true;
@@ -7965,14 +8418,45 @@ private:
7965 } 8418 }
7966 maxVar = getUnusedName("_max_"sv); 8419 maxVar = getUnusedName("_max_"sv);
7967 varBefore.push_back(maxVar); 8420 varBefore.push_back(maxVar);
7968 _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);
7969 } 8432 }
7970 _buf << indent() << "for "sv << indexVar << " = "sv; 8433 _buf << indent() << "for "sv << indexVar << " = "sv;
7971 _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;
7972 if (stopValue.empty()) { 8448 if (stopValue.empty()) {
7973 _buf << "#"sv << listVar; 8449 _buf << "#"sv << listVar;
7974 } else { 8450 } else {
7975 _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 }
7976 } 8460 }
7977 if (!stepValue.empty()) { 8461 if (!stepValue.empty()) {
7978 _buf << ", "sv << stepValue; 8462 _buf << ", "sv << stepValue;
@@ -8012,7 +8496,7 @@ private:
8012 pushScope(); 8496 pushScope();
8013 for (const auto& var : vars) forceAddToScope(var); 8497 for (const auto& var : vars) forceAddToScope(var);
8014 for (const auto& var : varAfter) addToScope(var); 8498 for (const auto& var : varAfter) addToScope(var);
8015 if (!varConstAfter.empty()) markVarConst(varConstAfter); 8499 if (!varConstAfter.empty()) markVarLocalConst(varConstAfter);
8016 if (!destructPairs.empty()) { 8500 if (!destructPairs.empty()) {
8017 temp.clear(); 8501 temp.clear();
8018 for (auto& pair : destructPairs) { 8502 for (auto& pair : destructPairs) {
@@ -8097,7 +8581,7 @@ private:
8097 _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);
8098 pushScope(); 8582 pushScope();
8099 forceAddToScope(varName); 8583 forceAddToScope(varName);
8100 markVarConst(varName); 8584 markVarLocalConst(varName);
8101 out.push_back(clearBuf()); 8585 out.push_back(clearBuf());
8102 } 8586 }
8103 8587
@@ -8105,26 +8589,59 @@ private:
8105 transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); 8589 transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out);
8106 } 8590 }
8107 8591
8108 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) {
8109 switch (body->get_id()) { 8593 switch (bodyOrStmt->get_id()) {
8110 case id<Block_t>(): 8594 case id<Block_t>():
8111 transformBlock(static_cast<Block_t*>(body), out, usage, assignList); 8595 transformBlock(static_cast<Block_t*>(bodyOrStmt), out, usage, assignList);
8112 break; 8596 break;
8113 case id<Statement_t>(): { 8597 case id<Statement_t>(): {
8114 auto newBlock = body->new_ptr<Block_t>(); 8598 auto newBlock = bodyOrStmt->new_ptr<Block_t>();
8115 newBlock->statements.push_back(body); 8599 newBlock->statements.push_back(bodyOrStmt);
8116 transformBlock(newBlock, out, usage, assignList); 8600 transformBlock(newBlock, out, usage, assignList);
8117 break; 8601 break;
8118 } 8602 }
8119 default: YUEE("AST node mismatch", body); break; 8603 default: YUEE("AST node mismatch", bodyOrStmt); break;
8120 } 8604 }
8121 } 8605 }
8122 8606
8123 bool hasContinueStatement(ast_node* body) { 8607 enum class BreakLoopType {
8124 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) {
8125 if (auto stmt = ast_cast<Statement_t>(node)) { 8629 if (auto stmt = ast_cast<Statement_t>(node)) {
8126 if (stmt->content.is<BreakLoop_t>()) { 8630 if (auto breakLoop = stmt->content.as<BreakLoop_t>()) {
8127 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 }
8128 } else if (auto expList = expListFrom(stmt)) { 8645 } else if (auto expList = expListFrom(stmt)) {
8129 BLOCK_START 8646 BLOCK_START
8130 auto value = singleValueFrom(expList); 8647 auto value = singleValueFrom(expList);
@@ -8135,40 +8652,30 @@ private:
8135 switch (sVal->get_id()) { 8652 switch (sVal->get_id()) {
8136 case id<With_t>(): { 8653 case id<With_t>(): {
8137 auto withNode = static_cast<With_t*>(sVal); 8654 auto withNode = static_cast<With_t*>(sVal);
8138 if (hasContinueStatement(withNode->body)) { 8655 type |= getBreakLoopType(withNode->body, varBWV);
8139 return traversal::Stop; 8656 return traversal::Return;
8140 }
8141 break;
8142 } 8657 }
8143 case id<Do_t>(): { 8658 case id<Do_t>(): {
8144 auto doNode = static_cast<Do_t*>(sVal); 8659 auto doNode = static_cast<Do_t*>(sVal);
8145 if (hasContinueStatement(doNode->body)) { 8660 type |= getBreakLoopType(doNode->body, varBWV);
8146 return traversal::Stop; 8661 return traversal::Return;
8147 }
8148 break;
8149 } 8662 }
8150 case id<If_t>(): { 8663 case id<If_t>(): {
8151 auto ifNode = static_cast<If_t*>(sVal); 8664 auto ifNode = static_cast<If_t*>(sVal);
8152 for (auto n : ifNode->nodes.objects()) { 8665 for (auto n : ifNode->nodes.objects()) {
8153 if (hasContinueStatement(n)) { 8666 type |= getBreakLoopType(n, varBWV);
8154 return traversal::Stop;
8155 }
8156 } 8667 }
8157 break; 8668 return traversal::Return;
8158 } 8669 }
8159 case id<Switch_t>(): { 8670 case id<Switch_t>(): {
8160 auto switchNode = static_cast<Switch_t*>(sVal); 8671 auto switchNode = static_cast<Switch_t*>(sVal);
8161 for (auto branch : switchNode->branches.objects()) { 8672 for (auto branch : switchNode->branches.objects()) {
8162 if (hasContinueStatement(static_cast<SwitchCase_t*>(branch)->body)) { 8673 type |= getBreakLoopType(static_cast<SwitchCase_t*>(branch)->body, varBWV);
8163 return traversal::Stop;
8164 }
8165 } 8674 }
8166 if (switchNode->lastBranch) { 8675 if (switchNode->lastBranch) {
8167 if (hasContinueStatement(switchNode->lastBranch)) { 8676 type |= getBreakLoopType(switchNode->lastBranch, varBWV);
8168 return traversal::Stop;
8169 }
8170 } 8677 }
8171 break; 8678 return traversal::Return;
8172 } 8679 }
8173 } 8680 }
8174 BLOCK_END 8681 BLOCK_END
@@ -8182,6 +8689,7 @@ private:
8182 } 8689 }
8183 return traversal::Return; 8690 return traversal::Return;
8184 }); 8691 });
8692 return type;
8185 } 8693 }
8186 8694
8187 void addDoToLastLineReturn(ast_node* body) { 8695 void addDoToLastLineReturn(ast_node* body) {
@@ -8205,10 +8713,10 @@ private:
8205 } 8713 }
8206 } 8714 }
8207 8715
8208 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) {
8209 str_list temp; 8717 str_list temp;
8210 bool extraDo = false; 8718 bool extraDo = false;
8211 bool withContinue = hasContinueStatement(body); 8719 bool withContinue = hasContinue(breakLoopType);
8212 int target = getLuaTarget(body); 8720 int target = getLuaTarget(body);
8213 std::string extraLabel; 8721 std::string extraLabel;
8214 if (withContinue) { 8722 if (withContinue) {
@@ -8217,7 +8725,7 @@ private:
8217 if (!block->statements.empty()) { 8725 if (!block->statements.empty()) {
8218 auto stmt = static_cast<Statement_t*>(block->statements.back()); 8726 auto stmt = static_cast<Statement_t*>(block->statements.back());
8219 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { 8727 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) {
8220 extraDo = _parser.toString(breakLoop) == "break"sv; 8728 extraDo = breakLoop->type.is<Break_t>();
8221 } 8729 }
8222 } 8730 }
8223 } 8731 }
@@ -8250,9 +8758,6 @@ private:
8250 popScope(); 8758 popScope();
8251 _buf << indent() << "end"sv << nll(body); 8759 _buf << indent() << "end"sv << nll(body);
8252 } 8760 }
8253 if (!appendContent.empty()) {
8254 _buf << indent() << appendContent;
8255 }
8256 _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); 8761 _buf << indent() << _continueVars.top().var << " = true"sv << nll(body);
8257 popScope(); 8762 popScope();
8258 _buf << indent() << "until true"sv << nlr(body); 8763 _buf << indent() << "until true"sv << nlr(body);
@@ -8262,14 +8767,9 @@ private:
8262 temp.push_back(clearBuf()); 8767 temp.push_back(clearBuf());
8263 _continueVars.pop(); 8768 _continueVars.pop();
8264 } else { 8769 } else {
8265 if (!appendContent.empty()) {
8266 temp.push_back(indent() + appendContent);
8267 }
8268 temp.push_back(extraLabel); 8770 temp.push_back(extraLabel);
8269 _continueVars.pop(); 8771 _continueVars.pop();
8270 } 8772 }
8271 } else if (!appendContent.empty()) {
8272 temp.back().append(indent() + appendContent);
8273 } 8773 }
8274 out.push_back(join(temp)); 8774 out.push_back(join(temp));
8275 } 8775 }
@@ -8277,8 +8777,9 @@ private:
8277 std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { 8777 std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) {
8278 str_list temp; 8778 str_list temp;
8279 bool extraDo = false; 8779 bool extraDo = false;
8280 auto body = repeatNode->body->content.get(); 8780 auto body = repeatNode->body.get();
8281 bool withContinue = hasContinueStatement(body); 8781 auto breakLoopType = getBreakLoopType(body, Empty);
8782 bool withContinue = hasContinue(breakLoopType);
8282 std::string conditionVar; 8783 std::string conditionVar;
8283 std::string extraLabel; 8784 std::string extraLabel;
8284 ast_ptr<false, ExpListAssign_t> condAssign; 8785 ast_ptr<false, ExpListAssign_t> condAssign;
@@ -8289,7 +8790,7 @@ private:
8289 if (!block->statements.empty()) { 8790 if (!block->statements.empty()) {
8290 auto stmt = static_cast<Statement_t*>(block->statements.back()); 8791 auto stmt = static_cast<Statement_t*>(block->statements.back());
8291 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { 8792 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) {
8292 extraDo = _parser.toString(breakLoop) == "break"sv; 8793 extraDo = breakLoop->type.is<Break_t>();
8293 } 8794 }
8294 } 8795 }
8295 } 8796 }
@@ -8352,7 +8853,8 @@ private:
8352 void transformFor(For_t* forNode, str_list& out) { 8853 void transformFor(For_t* forNode, str_list& out) {
8353 str_list temp; 8854 str_list temp;
8354 transformForHead(forNode, temp); 8855 transformForHead(forNode, temp);
8355 transformLoopBody(forNode->body, temp, Empty, ExpUsage::Common); 8856 auto breakLoopType = getBreakLoopType(forNode->body, Empty);
8857 transformLoopBody(forNode->body, temp, breakLoopType, ExpUsage::Common);
8356 popScope(); 8858 popScope();
8357 out.push_back(join(temp) + indent() + "end"s + nlr(forNode)); 8859 out.push_back(join(temp) + indent() + "end"s + nlr(forNode));
8358 } 8860 }
@@ -8363,13 +8865,24 @@ private:
8363 addToScope(accum); 8865 addToScope(accum);
8364 std::string len = getUnusedName("_len_"sv); 8866 std::string len = getUnusedName("_len_"sv);
8365 addToScope(len); 8867 addToScope(len);
8366 _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());
8367 _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); 8871 _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode);
8368 out.push_back(clearBuf()); 8872 auto& lenAssign = out.emplace_back(clearBuf());
8369 transformForHead(forNode, out); 8873 transformForHead(forNode, out);
8370 auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); 8874 if (hasBreakWithValue(breakLoopType)) {
8371 auto lenLine = len + " = "s + len + " + 1"s + nlr(forNode->body); 8875 lenAssign.clear();
8372 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 }
8373 popScope(); 8886 popScope();
8374 out.push_back(indent() + "end"s + nlr(forNode)); 8887 out.push_back(indent() + "end"s + nlr(forNode));
8375 return accum; 8888 return accum;
@@ -8448,7 +8961,8 @@ private:
8448 void transformForEach(ForEach_t* forEach, str_list& out) { 8961 void transformForEach(ForEach_t* forEach, str_list& out) {
8449 str_list temp; 8962 str_list temp;
8450 bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false); 8963 bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false);
8451 transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common); 8964 auto breakLoopType = getBreakLoopType(forEach->body, Empty);
8965 transformLoopBody(forEach->body, temp, breakLoopType, ExpUsage::Common);
8452 popScope(); 8966 popScope();
8453 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));
8454 if (extraScoped) { 8968 if (extraScoped) {
@@ -8463,13 +8977,24 @@ private:
8463 addToScope(accum); 8977 addToScope(accum);
8464 std::string len = getUnusedName("_len_"sv); 8978 std::string len = getUnusedName("_len_"sv);
8465 addToScope(len); 8979 addToScope(len);
8466 _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());
8467 _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); 8983 _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach);
8468 out.push_back(clearBuf()); 8984 auto& lenAssign = out.emplace_back(clearBuf());
8469 transformForEachHead(forEach->nameList, forEach->loopValue, out, true); 8985 transformForEachHead(forEach->nameList, forEach->loopValue, out, true);
8470 auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); 8986 if (hasBreakWithValue(breakLoopType)) {
8471 auto lenLine = len + " = "s + len + " + 1"s + nlr(forEach->body); 8987 lenAssign.clear();
8472 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 }
8473 popScope(); 8998 popScope();
8474 out.push_back(indent() + "end"s + nlr(forEach)); 8999 out.push_back(indent() + "end"s + nlr(forEach));
8475 return accum; 9000 return accum;
@@ -8653,12 +9178,64 @@ private:
8653 out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); 9178 out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv));
8654 } 9179 }
8655 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
8656 void transformString(String_t* string, str_list& out) { 9232 void transformString(String_t* string, str_list& out) {
8657 auto str = string->str.get(); 9233 auto str = string->str.get();
8658 switch (str->get_id()) { 9234 switch (str->get_id()) {
8659 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;
8660 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;
8661 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;
8662 default: YUEE("AST node mismatch", str); break; 9239 default: YUEE("AST node mismatch", str); break;
8663 } 9240 }
8664 } 9241 }
@@ -8840,7 +9417,7 @@ private:
8840 auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get); 9417 auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get);
8841 for (const auto& name : names) { 9418 for (const auto& name : names) {
8842 forceAddToScope(name.first); 9419 forceAddToScope(name.first);
8843 markVarConst(name.first); 9420 markVarLocalConst(name.first);
8844 varDefs.push_back(name.first); 9421 varDefs.push_back(name.first);
8845 classConstVars.push_back(name.first); 9422 classConstVars.push_back(name.first);
8846 } 9423 }
@@ -8854,7 +9431,7 @@ private:
8854 for (const auto& item : destruct.items) { 9431 for (const auto& item : destruct.items) {
8855 if (!item.targetVar.empty()) { 9432 if (!item.targetVar.empty()) {
8856 forceAddToScope(item.targetVar); 9433 forceAddToScope(item.targetVar);
8857 markVarConst(item.targetVar); 9434 markVarLocalConst(item.targetVar);
8858 varDefs.push_back(item.targetVar); 9435 varDefs.push_back(item.targetVar);
8859 classConstVars.push_back(item.targetVar); 9436 classConstVars.push_back(item.targetVar);
8860 } 9437 }
@@ -9236,11 +9813,11 @@ private:
9236 std::string withVar; 9813 std::string withVar;
9237 bool needScope = !currentScope().lastStatement && !returnValue; 9814 bool needScope = !currentScope().lastStatement && !returnValue;
9238 bool extraScope = false; 9815 bool extraScope = false;
9239 if (with->assigns) { 9816 if (with->assign) {
9240 auto vars = getAssignVars(with); 9817 auto vars = getAssignVars(with);
9241 if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { 9818 if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) {
9242 if (with->assigns->values.objects().size() == 1) { 9819 if (with->assign->values.objects().size() == 1) {
9243 auto var = singleVariableFrom(with->assigns->values.objects().front(), AccessType::Read); 9820 auto var = singleVariableFrom(with->assign->values.objects().front(), AccessType::Read);
9244 if (!var.empty() && isLocal(var)) { 9821 if (!var.empty() && isLocal(var)) {
9245 withVar = var; 9822 withVar = var;
9246 } 9823 }
@@ -9250,7 +9827,7 @@ private:
9250 auto assignment = x->new_ptr<ExpListAssign_t>(); 9827 auto assignment = x->new_ptr<ExpListAssign_t>();
9251 assignment->expList.set(toAst<ExpList_t>(withVar, x)); 9828 assignment->expList.set(toAst<ExpList_t>(withVar, x));
9252 auto assign = x->new_ptr<Assign_t>(); 9829 auto assign = x->new_ptr<Assign_t>();
9253 assign->values.push_back(with->assigns->values.objects().front()); 9830 assign->values.push_back(with->assign->values.objects().front());
9254 assignment->action.set(assign); 9831 assignment->action.set(assign);
9255 if (needScope) { 9832 if (needScope) {
9256 extraScope = true; 9833 extraScope = true;
@@ -9264,7 +9841,7 @@ private:
9264 auto assign = x->new_ptr<Assign_t>(); 9841 auto assign = x->new_ptr<Assign_t>();
9265 assign->values.push_back(toAst<Exp_t>(withVar, x)); 9842 assign->values.push_back(toAst<Exp_t>(withVar, x));
9266 bool skipFirst = true; 9843 bool skipFirst = true;
9267 for (auto value : with->assigns->values.objects()) { 9844 for (auto value : with->assign->values.objects()) {
9268 if (skipFirst) { 9845 if (skipFirst) {
9269 skipFirst = false; 9846 skipFirst = false;
9270 continue; 9847 continue;
@@ -9277,7 +9854,7 @@ private:
9277 withVar = vars.front(); 9854 withVar = vars.front();
9278 auto assignment = x->new_ptr<ExpListAssign_t>(); 9855 auto assignment = x->new_ptr<ExpListAssign_t>();
9279 assignment->expList.set(with->valueList); 9856 assignment->expList.set(with->valueList);
9280 assignment->action.set(with->assigns); 9857 assignment->action.set(with->assign);
9281 if (needScope) { 9858 if (needScope) {
9282 extraScope = true; 9859 extraScope = true;
9283 temp.push_back(indent() + "do"s + nll(with)); 9860 temp.push_back(indent() + "do"s + nll(with));
@@ -9355,15 +9932,57 @@ private:
9355 } 9932 }
9356 } 9933 }
9357 _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 }
9358 if (with->eop) { 9942 if (with->eop) {
9359 auto ifNode = x->new_ptr<If_t>(); 9943 auto ifNode = x->new_ptr<If_t>();
9360 ifNode->type.set(toAst<IfType_t>("if"sv, x)); 9944 ifNode->type.set(toAst<IfType_t>("if"sv, x));
9361 ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); 9945 ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x));
9362 ifNode->nodes.push_back(with->body); 9946 ifNode->nodes.push_back(with->body);
9363 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 }
9364 } else { 9968 } else {
9365 bool transformed = false; 9969 bool transformed = false;
9366 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) {
9367 if (auto block = with->body.as<Block_t>()) { 9986 if (auto block = with->body.as<Block_t>()) {
9368 if (!block->statements.empty()) { 9987 if (!block->statements.empty()) {
9369 Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); 9988 Statement_t* stmt = static_cast<Statement_t*>(block->statements.back());
@@ -9428,12 +10047,18 @@ private:
9428 switch (item->get_id()) { 10047 switch (item->get_id()) {
9429 case id<ClassDecl_t>(): { 10048 case id<ClassDecl_t>(): {
9430 auto classDecl = static_cast<ClassDecl_t*>(item); 10049 auto classDecl = static_cast<ClassDecl_t*>(item);
10050 std::string varName;
9431 if (classDecl->name) { 10051 if (classDecl->name) {
9432 if (auto var = classDecl->name->item.as<Variable_t>()) { 10052 if (auto var = classDecl->name->item.as<Variable_t>()) {
9433 addGlobalVar(variableToString(var), classDecl->name->item); 10053 varName = variableToString(var);
10054 addGlobalVar(varName, var);
9434 } 10055 }
9435 } 10056 }
10057 if (varName.empty()) {
10058 throw CompileError("missing name for class", classDecl);
10059 }
9436 transformClassDecl(classDecl, out, ExpUsage::Common); 10060 transformClassDecl(classDecl, out, ExpUsage::Common);
10061 markVarGlobalConst(varName);
9437 break; 10062 break;
9438 } 10063 }
9439 case id<GlobalOp_t>(): 10064 case id<GlobalOp_t>():
@@ -9447,9 +10072,11 @@ private:
9447 auto values = global->item.to<GlobalValues_t>(); 10072 auto values = global->item.to<GlobalValues_t>();
9448 if (values->valueList) { 10073 if (values->valueList) {
9449 auto expList = x->new_ptr<ExpList_t>(); 10074 auto expList = x->new_ptr<ExpList_t>();
10075 str_list varNames;
9450 for (auto name : values->nameList->names.objects()) { 10076 for (auto name : values->nameList->names.objects()) {
9451 auto var = static_cast<Variable_t*>(name); 10077 auto var = static_cast<Variable_t*>(name);
9452 addGlobalVar(variableToString(var), var); 10078 varNames.emplace_back(variableToString(var));
10079 addGlobalVar(varNames.back(), var);
9453 auto callable = x->new_ptr<Callable_t>(); 10080 auto callable = x->new_ptr<Callable_t>();
9454 callable->item.set(name); 10081 callable->item.set(name);
9455 auto chainValue = x->new_ptr<ChainValue_t>(); 10082 auto chainValue = x->new_ptr<ChainValue_t>();
@@ -9468,10 +10095,17 @@ private:
9468 } 10095 }
9469 assignment->action.set(assign); 10096 assignment->action.set(assign);
9470 transformAssignment(assignment, out); 10097 transformAssignment(assignment, out);
10098 for (const auto& name : varNames) {
10099 markVarGlobalConst(name);
10100 }
9471 } else { 10101 } else {
9472 for (auto name : values->nameList->names.objects()) { 10102 for (auto name : values->nameList->names.objects()) {
9473 auto var = static_cast<Variable_t*>(name); 10103 auto var = static_cast<Variable_t*>(name);
9474 addGlobalVar(variableToString(var), var); 10104 auto varName = variableToString(var);
10105 addGlobalVar(varName, var);
10106 if (global->constAttrib) {
10107 markVarGlobalConst(varName);
10108 }
9475 } 10109 }
9476 } 10110 }
9477 break; 10111 break;
@@ -9820,8 +10454,47 @@ private:
9820 out.push_back(join(temp)); 10454 out.push_back(join(temp));
9821 } 10455 }
9822 10456
9823 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) {
9824 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 }
9825 ast_ptr<true, Exp_t> errHandler; 10498 ast_ptr<true, Exp_t> errHandler;
9826 if (tryNode->catchBlock) { 10499 if (tryNode->catchBlock) {
9827 auto catchBlock = tryNode->catchBlock.get(); 10500 auto catchBlock = tryNode->catchBlock.get();
@@ -10133,7 +10806,7 @@ private:
10133 out.push_back(join(temp)); 10806 out.push_back(join(temp));
10134 auto vars = getAssignVars(assignment); 10807 auto vars = getAssignVars(assignment);
10135 for (const auto& var : vars) { 10808 for (const auto& var : vars) {
10136 markVarConst(var); 10809 markVarLocalConst(var);
10137 } 10810 }
10138 } 10811 }
10139 10812
@@ -10361,12 +11034,36 @@ private:
10361 transformAssignment(assignment, out); 11034 transformAssignment(assignment, out);
10362 if (auto var = ast_cast<Variable_t>(target)) { 11035 if (auto var = ast_cast<Variable_t>(target)) {
10363 auto moduleName = variableToString(var); 11036 auto moduleName = variableToString(var);
10364 markVarConst(moduleName); 11037 markVarLocalConst(moduleName);
10365 } else { 11038 } else {
10366 markDestructureConst(assignment); 11039 markDestructureConst(assignment);
10367 } 11040 }
10368 } 11041 }
10369 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
10370 void transformImport(Import_t* import, str_list& out) { 11067 void transformImport(Import_t* import, str_list& out) {
10371 auto content = import->content.get(); 11068 auto content = import->content.get();
10372 switch (content->get_id()) { 11069 switch (content->get_id()) {
@@ -10379,6 +11076,9 @@ private:
10379 case id<FromImport_t>(): 11076 case id<FromImport_t>():
10380 transformFromImport(static_cast<FromImport_t*>(content), out); 11077 transformFromImport(static_cast<FromImport_t*>(content), out);
10381 break; 11078 break;
11079 case id<ImportGlobal_t>():
11080 transformImportGlobal(static_cast<ImportGlobal_t*>(content), out);
11081 break;
10382 default: YUEE("AST node mismatch", content); break; 11082 default: YUEE("AST node mismatch", content); break;
10383 } 11083 }
10384 } 11084 }
@@ -10398,15 +11098,27 @@ private:
10398 addToScope(accumVar); 11098 addToScope(accumVar);
10399 auto lenVar = getUnusedName("_len_"sv); 11099 auto lenVar = getUnusedName("_len_"sv);
10400 addToScope(lenVar); 11100 addToScope(lenVar);
10401 temp.push_back(indent() + "local "s + accumVar + " = { }"s + nll(whileNode)); 11101 auto breakLoopType = getBreakLoopType(whileNode->body, accumVar);
10402 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());
10403 bool isUntil = _parser.toString(whileNode->type) == "until"sv; 11106 bool isUntil = _parser.toString(whileNode->type) == "until"sv;
10404 auto condStr = transformCondExp(whileNode->condition, isUntil); 11107 auto condStr = transformCondExp(whileNode->condition, isUntil);
10405 temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); 11108 temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode));
10406 pushScope(); 11109 pushScope();
10407 auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); 11110 if (hasBreakWithValue(breakLoopType)) {
10408 auto lenLine = lenVar + " = "s + lenVar + " + 1"s + nlr(whileNode); 11111 lenAssign.clear();
10409 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 }
10410 popScope(); 11122 popScope();
10411 temp.push_back(indent() + "end"s + nlr(whileNode)); 11123 temp.push_back(indent() + "end"s + nlr(whileNode));
10412 if (expList) { 11124 if (expList) {
@@ -10442,15 +11154,26 @@ private:
10442 addToScope(accumVar); 11154 addToScope(accumVar);
10443 auto lenVar = getUnusedName("_len_"sv); 11155 auto lenVar = getUnusedName("_len_"sv);
10444 addToScope(lenVar); 11156 addToScope(lenVar);
10445 temp.push_back(indent() + "local "s + accumVar + " = { }"s + nll(whileNode)); 11157 auto breakLoopType = getBreakLoopType(whileNode->body, accumVar);
10446 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));
10447 bool isUntil = _parser.toString(whileNode->type) == "until"sv; 11161 bool isUntil = _parser.toString(whileNode->type) == "until"sv;
10448 auto condStr = transformCondExp(whileNode->condition, isUntil); 11162 auto condStr = transformCondExp(whileNode->condition, isUntil);
10449 temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); 11163 temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode));
10450 pushScope(); 11164 pushScope();
10451 auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); 11165 if (hasBreakWithValue(breakLoopType)) {
10452 auto lenLine = lenVar + " = "s + lenVar + " + 1"s + nlr(whileNode); 11166 lenAssign.clear();
10453 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 }
10454 popScope(); 11177 popScope();
10455 temp.push_back(indent() + "end"s + nlr(whileNode)); 11178 temp.push_back(indent() + "end"s + nlr(whileNode));
10456 temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); 11179 temp.push_back(indent() + "return "s + accumVar + nlr(whileNode));
@@ -10485,9 +11208,7 @@ private:
10485 expListAssign->expList.set(expList); 11208 expListAssign->expList.set(expList);
10486 auto stmt = x->new_ptr<Statement_t>(); 11209 auto stmt = x->new_ptr<Statement_t>();
10487 stmt->content.set(expListAssign); 11210 stmt->content.set(expListAssign);
10488 auto body = x->new_ptr<Body_t>(); 11211 repeat->body.set(stmt);
10489 body->content.set(stmt);
10490 repeat->body.set(body);
10491 transformRepeat(repeat, out); 11212 transformRepeat(repeat, out);
10492 return; 11213 return;
10493 } 11214 }
@@ -10495,7 +11216,8 @@ private:
10495 pushScope(); 11216 pushScope();
10496 bool isUntil = _parser.toString(whileNode->type) == "until"sv; 11217 bool isUntil = _parser.toString(whileNode->type) == "until"sv;
10497 auto condStr = transformCondExp(whileNode->condition, isUntil); 11218 auto condStr = transformCondExp(whileNode->condition, isUntil);
10498 transformLoopBody(whileNode->body, temp, Empty, ExpUsage::Common); 11219 auto breakLoopType = getBreakLoopType(whileNode->body, Empty);
11220 transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common);
10499 popScope(); 11221 popScope();
10500 _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode); 11222 _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode);
10501 _buf << temp.back(); 11223 _buf << temp.back();
@@ -10503,6 +11225,106 @@ private:
10503 out.push_back(clearBuf()); 11225 out.push_back(clearBuf());
10504 } 11226 }
10505 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
10506 void transformRepeat(Repeat_t* repeat, str_list& out) { 11328 void transformRepeat(Repeat_t* repeat, str_list& out) {
10507 str_list temp; 11329 str_list temp;
10508 pushScope(); 11330 pushScope();
@@ -10536,10 +11358,26 @@ private:
10536 pushScope(); 11358 pushScope();
10537 } 11359 }
10538 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 }
10539 auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); 11377 auto objVar = singleVariableFrom(switchNode->target, AccessType::Read);
10540 if (objVar.empty() || !isLocal(objVar)) { 11378 if (objVar.empty() || !isLocal(objVar)) {
10541 if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { 11379 if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) {
10542 if (needScope) { 11380 if (needScope && !extraScope) {
10543 extraScope = true; 11381 extraScope = true;
10544 temp.push_back(indent() + "do"s + nll(x)); 11382 temp.push_back(indent() + "do"s + nll(x));
10545 pushScope(); 11383 pushScope();
@@ -10597,8 +11435,9 @@ private:
10597 } 11435 }
10598 temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); 11436 temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch));
10599 pushScope(); 11437 pushScope();
10600 auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), toAst<Exp_t>(objVar, branch), branch); 11438 auto chainValue = toAst<ChainValue_t>(objVar, branch);
10601 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);
10602 transformAssignment(assignment, temp, true); 11441 transformAssignment(assignment, temp, true);
10603 str_list conds; 11442 str_list conds;
10604 for (const auto& des : info.destructures) { 11443 for (const auto& des : info.destructures) {
@@ -10608,8 +11447,31 @@ private:
10608 const auto& destruct = std::get<Destructure>(des); 11447 const auto& destruct = std::get<Destructure>(des);
10609 for (const auto& item : destruct.items) { 11448 for (const auto& item : destruct.items) {
10610 if (!item.defVal) { 11449 if (!item.defVal) {
10611 transformExp(item.target, conds, ExpUsage::Closure); 11450 if (!isAssignable(item.target)) {
10612 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 }
10613 } 11475 }
10614 } 11476 }
10615 } 11477 }
@@ -10907,7 +11769,7 @@ private:
10907 } 11769 }
10908 transformAssignment(assignment, temp); 11770 transformAssignment(assignment, temp);
10909 for (const auto& name : vars) { 11771 for (const auto& name : vars) {
10910 markVarConst(name); 11772 markVarLocalConst(name);
10911 } 11773 }
10912 if (localAttrib->attrib.is<CloseAttrib_t>()) { 11774 if (localAttrib->attrib.is<CloseAttrib_t>()) {
10913 str_list leftVars, rightVars; 11775 str_list leftVars, rightVars;
@@ -10979,7 +11841,7 @@ private:
10979 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));
10980 } 11842 }
10981 for (const auto& var : vars) { 11843 for (const auto& var : vars) {
10982 markVarConst(var); 11844 markVarLocalConst(var);
10983 } 11845 }
10984 } 11846 }
10985 if (!listB->exprs.empty()) { 11847 if (!listB->exprs.empty()) {
@@ -11004,18 +11866,24 @@ private:
11004 temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); 11866 temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x));
11005 transformAssignment(assignment, temp); 11867 transformAssignment(assignment, temp);
11006 for (const auto& name : vars) { 11868 for (const auto& name : vars) {
11007 markVarConst(name); 11869 markVarLocalConst(name);
11008 } 11870 }
11009 } 11871 }
11010 out.push_back(join(temp)); 11872 out.push_back(join(temp));
11011 } 11873 }
11012 11874
11013 void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { 11875 void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) {
11014 auto keyword = _parser.toString(breakLoop); 11876 auto isBreak = breakLoop->type.is<Break_t>();
11877 auto keyword = isBreak ? "break"s : "continue"s;
11015 if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { 11878 if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) {
11016 throw CompileError(keyword + " is not inside a loop"s, breakLoop); 11879 throw CompileError(keyword + " is not inside a loop"s, breakLoop);
11017 } 11880 }
11018 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 }
11019 out.push_back(indent() + keyword + nll(breakLoop)); 11887 out.push_back(indent() + keyword + nll(breakLoop));
11020 return; 11888 return;
11021 } 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 77c5901..1942e23 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -118,8 +118,8 @@ YueParser::YueParser() {
118 return false; 118 return false;
119 }); 119 });
120 120
121 if_assignment_syntax_error = pl::user(true_(), [](const item_t& item) { 121 assignment_expression_syntax_error = pl::user(true_(), [](const item_t& item) {
122 throw ParserError("use := for if-assignment expression"sv, item.begin); 122 throw ParserError("use := for assignment expression"sv, item.begin);
123 return false; 123 return false;
124 }); 124 });
125 125
@@ -162,6 +162,13 @@ YueParser::YueParser() {
162 ) \ 162 ) \
163 ) 163 )
164 164
165 #define disable_until_rule(patt) ( \
166 disable_until >> ( \
167 (patt) >> enable_until | \
168 enable_until >> cut \
169 ) \
170 )
171
165 #define body_with(str) ( \ 172 #define body_with(str) ( \
166 key(str) >> space >> (in_block | Statement) | \ 173 key(str) >> space >> (in_block | Statement) | \
167 in_block | \ 174 in_block | \
@@ -325,7 +332,7 @@ YueParser::YueParser() {
325 Exp; 332 Exp;
326 import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); 333 import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item);
327 import_tab_line = ( 334 import_tab_line = (
328 push_indent_match >> (space >> import_tab_list >> pop_indent | pop_indent) 335 push_indent_match >> ensure(space >> import_tab_list, pop_indent)
329 ) | space; 336 ) | space;
330 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 >> ',');
331 import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; 338 import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro;
@@ -342,7 +349,9 @@ YueParser::YueParser() {
342 349
343 ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro)); 350 ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro));
344 351
345 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;
346 355
347 Label = "::" >> LabelName >> "::"; 356 Label = "::" >> LabelName >> "::";
348 357
@@ -350,11 +359,13 @@ YueParser::YueParser() {
350 359
351 ShortTabAppending = "[]" >> space >> Assign; 360 ShortTabAppending = "[]" >> space >> Assign;
352 361
353 BreakLoop = (expr("break") | "continue") >> not_alpha_num; 362 Break = key("break");
363 Continue = key("continue");
364 BreakLoop = (Break >> -(space >> Exp) | Continue) >> not_alpha_num;
354 365
355 Return = key("return") >> -(space >> (TableBlock | ExpListLow)); 366 Return = key("return") >> -(space >> (TableBlock | ExpListLow));
356 367
357 with_exp = ExpList >> -(space >> Assign); 368 with_exp = ExpList >> -(space >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error));
358 369
359 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");
360 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");
@@ -370,7 +381,8 @@ YueParser::YueParser() {
370 and_(SimpleTable | TableLit) >> Exp | 381 and_(SimpleTable | TableLit) >> Exp |
371 exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) 382 exp_not_tab >> *(space >> ',' >> space >> exp_not_tab)
372 ); 383 );
373 Switch = key("switch") >> space >> Exp >> 384 Switch = key("switch") >> space >>
385 Exp >> -(space >> Assignment) >>
374 space >> Seperator >> ( 386 space >> Seperator >> (
375 SwitchCase >> space >> ( 387 SwitchCase >> space >> (
376 switch_block | 388 switch_block |
@@ -379,20 +391,26 @@ YueParser::YueParser() {
379 +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent 391 +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent
380 ); 392 );
381 393
382 Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error); 394 Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error);
383 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)));
384 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");
385 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;
386 IfType = (expr("if") | "unless") >> not_alpha_num; 398 IfType = (expr("if") | "unless") >> not_alpha_num;
387 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;
388 400
389 WhileType = (expr("while") | "until") >> not_alpha_num; 401 WhileType = (expr("while") | pl::user("until", [](const item_t& item) {
390 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);
391 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;
392 410
393 for_key = pl::user(key("for"), [](const item_t& item) { 411 for_key = pl::user(key("for"), [](const item_t& item) {
394 State* st = reinterpret_cast<State*>(item.user_data); 412 State* st = reinterpret_cast<State*>(item.user_data);
395 return st->noForStack.empty() || !st->noForStack.top(); 413 return st->noForStack.empty() || !st->noForStack.back();
396 }); 414 });
397 ForStepValue = ',' >> space >> Exp; 415 ForStepValue = ',' >> space >> Exp;
398 for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; 416 for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue;
@@ -406,18 +424,18 @@ YueParser::YueParser() {
406 424
407 Do = pl::user(key("do"), [](const item_t& item) { 425 Do = pl::user(key("do"), [](const item_t& item) {
408 State* st = reinterpret_cast<State*>(item.user_data); 426 State* st = reinterpret_cast<State*>(item.user_data);
409 return st->noDoStack.empty() || !st->noDoStack.top(); 427 return st->noDoStack.empty() || !st->noDoStack.back();
410 }) >> space >> Body; 428 }) >> space >> Body;
411 429
412 disable_do = pl::user(true_(), [](const item_t& item) { 430 disable_do = pl::user(true_(), [](const item_t& item) {
413 State* st = reinterpret_cast<State*>(item.user_data); 431 State* st = reinterpret_cast<State*>(item.user_data);
414 st->noDoStack.push(true); 432 st->noDoStack.push_back(true);
415 return true; 433 return true;
416 }); 434 });
417 435
418 enable_do = pl::user(true_(), [](const item_t& item) { 436 enable_do = pl::user(true_(), [](const item_t& item) {
419 State* st = reinterpret_cast<State*>(item.user_data); 437 State* st = reinterpret_cast<State*>(item.user_data);
420 st->noDoStack.pop(); 438 st->noDoStack.pop_back();
421 return true; 439 return true;
422 }); 440 });
423 441
@@ -435,46 +453,58 @@ YueParser::YueParser() {
435 453
436 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) {
437 State* st = reinterpret_cast<State*>(item.user_data); 455 State* st = reinterpret_cast<State*>(item.user_data);
438 st->noDoStack.push(true); 456 st->noDoStack.push_back(true);
439 st->noChainBlockStack.push(true); 457 st->noChainBlockStack.push_back(true);
440 st->noTableBlockStack.push(true); 458 st->noTableBlockStack.push_back(true);
441 return true; 459 return true;
442 }); 460 });
443 461
444 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) {
445 State* st = reinterpret_cast<State*>(item.user_data); 463 State* st = reinterpret_cast<State*>(item.user_data);
446 st->noDoStack.pop(); 464 st->noDoStack.pop_back();
447 st->noChainBlockStack.pop(); 465 st->noChainBlockStack.pop_back();
448 st->noTableBlockStack.pop(); 466 st->noTableBlockStack.pop_back();
449 return true; 467 return true;
450 }); 468 });
451 469
452 disable_arg_table_block = pl::user(true_(), [](const item_t& item) { 470 disable_arg_table_block = pl::user(true_(), [](const item_t& item) {
453 State* st = reinterpret_cast<State*>(item.user_data); 471 State* st = reinterpret_cast<State*>(item.user_data);
454 st->noTableBlockStack.push(true); 472 st->noTableBlockStack.push_back(true);
455 return true; 473 return true;
456 }); 474 });
457 475
458 enable_arg_table_block = pl::user(true_(), [](const item_t& item) { 476 enable_arg_table_block = pl::user(true_(), [](const item_t& item) {
459 State* st = reinterpret_cast<State*>(item.user_data); 477 State* st = reinterpret_cast<State*>(item.user_data);
460 st->noTableBlockStack.pop(); 478 st->noTableBlockStack.pop_back();
461 return true; 479 return true;
462 }); 480 });
463 481
464 disable_for = pl::user(true_(), [](const item_t& item) { 482 disable_for = pl::user(true_(), [](const item_t& item) {
465 State* st = reinterpret_cast<State*>(item.user_data); 483 State* st = reinterpret_cast<State*>(item.user_data);
466 st->noForStack.push(true); 484 st->noForStack.push_back(true);
467 return true; 485 return true;
468 }); 486 });
469 487
470 enable_for = pl::user(true_(), [](const item_t& item) { 488 enable_for = pl::user(true_(), [](const item_t& item) {
471 State* st = reinterpret_cast<State*>(item.user_data); 489 State* st = reinterpret_cast<State*>(item.user_data);
472 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();
473 return true; 503 return true;
474 }); 504 });
475 505
476 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;
477 Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; 507 Try = key("try") >> -ExistentialOp >> space >> (in_block | Exp) >> -CatchBlock;
478 508
479 list_value = 509 list_value =
480 and_( 510 and_(
@@ -561,20 +591,20 @@ YueParser::YueParser() {
561 591
562 disable_chain = pl::user(true_(), [](const item_t& item) { 592 disable_chain = pl::user(true_(), [](const item_t& item) {
563 State* st = reinterpret_cast<State*>(item.user_data); 593 State* st = reinterpret_cast<State*>(item.user_data);
564 st->noChainBlockStack.push(true); 594 st->noChainBlockStack.push_back(true);
565 return true; 595 return true;
566 }); 596 });
567 597
568 enable_chain = pl::user(true_(), [](const item_t& item) { 598 enable_chain = pl::user(true_(), [](const item_t& item) {
569 State* st = reinterpret_cast<State*>(item.user_data); 599 State* st = reinterpret_cast<State*>(item.user_data);
570 st->noChainBlockStack.pop(); 600 st->noChainBlockStack.pop_back();
571 return true; 601 return true;
572 }); 602 });
573 603
574 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;
575 chain_block = pl::user(true_(), [](const item_t& item) { 605 chain_block = pl::user(true_(), [](const item_t& item) {
576 State* st = reinterpret_cast<State*>(item.user_data); 606 State* st = reinterpret_cast<State*>(item.user_data);
577 return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); 607 return st->noChainBlockStack.empty() || !st->noChainBlockStack.back();
578 }) >> +space_break >> advance_match >> ensure( 608 }) >> +space_break >> advance_match >> ensure(
579 chain_line >> *(+space_break >> chain_line), pop_indent); 609 chain_line >> *(+space_break >> chain_line), pop_indent);
580 ChainValue = 610 ChainValue =
@@ -611,7 +641,15 @@ YueParser::YueParser() {
611 DoubleStringInner = +(not_("#{") >> double_string_plain); 641 DoubleStringInner = +(not_("#{") >> double_string_plain);
612 DoubleStringContent = DoubleStringInner | interp; 642 DoubleStringContent = DoubleStringInner | interp;
613 DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; 643 DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"';
614 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;
615 653
616 lua_string_open = '[' >> *expr('=') >> '['; 654 lua_string_open = '[' >> *expr('=') >> '[';
617 lua_string_close = ']' >> *expr('=') >> ']'; 655 lua_string_close = ']' >> *expr('=') >> ']';
@@ -639,7 +677,7 @@ YueParser::YueParser() {
639 fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); 677 fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp);
640 678
641 fn_args_lit_line = ( 679 fn_args_lit_line = (
642 push_indent_match >> (space >> fn_args_value_list >> pop_indent | pop_indent) 680 push_indent_match >> ensure(space >> fn_args_value_list, pop_indent)
643 ) | ( 681 ) | (
644 space 682 space
645 ); 683 );
@@ -681,7 +719,8 @@ YueParser::YueParser() {
681 chain_with_colon = +chain_item >> -colon_chain; 719 chain_with_colon = +chain_item >> -colon_chain;
682 chain_items = chain_with_colon | colon_chain; 720 chain_items = chain_with_colon | colon_chain;
683 721
684 index = '[' >> not_('[') >> space >> Exp >> space >> ']'; 722 index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']';
723 ReversedIndex = '#' >> space >> -('-' >> space >> Exp);
685 chain_item = 724 chain_item =
686 Invoke >> -ExistentialOp | 725 Invoke >> -ExistentialOp |
687 DotChainItem >> -ExistentialOp | 726 DotChainItem >> -ExistentialOp |
@@ -738,7 +777,7 @@ YueParser::YueParser() {
738 777
739 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);
740 TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); 779 TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent);
741 TableBlockIndent = '*' >> Seperator >> disable_arg_table_block_rule( 780 TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule(
742 space >> key_value_list >> -(space >> ',') >> 781 space >> key_value_list >> -(space >> ',') >>
743 -(+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)));
744 783
@@ -759,7 +798,7 @@ YueParser::YueParser() {
759 798
760 GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); 799 GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow));
761 GlobalOp = expr('*') | '^'; 800 GlobalOp = expr('*') | '^';
762 Global = key("global") >> space >> (ClassDecl | GlobalOp | GlobalValues); 801 Global = key("global") >> space >> (-(ConstAttrib >> space) >> ClassDecl | GlobalOp | -(ConstAttrib >> space) >> GlobalValues);
763 802
764 ExportDefault = key("default"); 803 ExportDefault = key("default");
765 804
@@ -841,24 +880,24 @@ YueParser::YueParser() {
841 key_value_line = check_indent_match >> space >> ( 880 key_value_line = check_indent_match >> space >> (
842 key_value_list >> -(space >> ',') | 881 key_value_list >> -(space >> ',') |
843 TableBlockIndent | 882 TableBlockIndent |
844 '*' >> space >> (SpreadExp | Exp | TableBlock) 883 ('*' | '-' >> space_one) >> space >> (SpreadExp | Exp | TableBlock)
845 ); 884 );
846 885
847 fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); 886 fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef);
848 887
849 fn_arg_def_lit_line = ( 888 fn_arg_def_lit_line = (
850 push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent) 889 push_indent_match >> ensure(space >> fn_arg_def_list, pop_indent)
851 ) | ( 890 ) | (
852 space 891 space
853 ); 892 );
854 893
855 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);
856 895
857 FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); 896 FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp);
858 897
859 FnArgDefList = Seperator >> ( 898 FnArgDefList = Seperator >> (
860 fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) | 899 fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg >> -(space >> '`' >> space >> Name)) |
861 white >> VarArg 900 white >> VarArg >> -(space >> '`' >> space >> Name)
862 ); 901 );
863 902
864 OuterVarShadow = key("using") >> space >> (NameList | key("nil")); 903 OuterVarShadow = key("using") >> space >> (NameList | key("nil"));
@@ -887,6 +926,7 @@ YueParser::YueParser() {
887 926
888 FnArrowBack = '<' >> set("-="); 927 FnArrowBack = '<' >> set("-=");
889 Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; 928 Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue;
929 SubBackcall = FnArrowBack >> space >> ChainValue;
890 930
891 PipeBody = Seperator >> 931 PipeBody = Seperator >>
892 pipe_operator >> space >> UnaryExp >> 932 pipe_operator >> space >> UnaryExp >>
@@ -900,7 +940,7 @@ YueParser::YueParser() {
900 940
901 arg_table_block = pl::user(true_(), [](const item_t& item) { 941 arg_table_block = pl::user(true_(), [](const item_t& item) {
902 State* st = reinterpret_cast<State*>(item.user_data); 942 State* st = reinterpret_cast<State*>(item.user_data);
903 return st->noTableBlockStack.empty() || !st->noTableBlockStack.top(); 943 return st->noTableBlockStack.empty() || !st->noTableBlockStack.back();
904 }) >> TableBlock; 944 }) >> TableBlock;
905 945
906 invoke_args_with_table = 946 invoke_args_with_table =
@@ -940,11 +980,11 @@ YueParser::YueParser() {
940 980
941 SimpleValue = 981 SimpleValue =
942 TableLit | ConstValue | If | Switch | Try | With | 982 TableLit | ConstValue | If | Switch | Try | With |
943 ClassDecl | ForEach | For | While | Do | 983 ClassDecl | ForEach | For | While | Repeat | Do |
944 UnaryValue | TblComprehension | Comprehension | 984 UnaryValue | TblComprehension | Comprehension |
945 FunLit | Num | VarArg; 985 FunLit | Num | VarArg;
946 986
947 ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '='); 987 ExpListAssign = ExpList >> -(space >> (Update | Assign | SubBackcall)) >> not_(space >> '=');
948 988
949 IfLine = IfType >> space >> IfCond; 989 IfLine = IfType >> space >> IfCond;
950 WhileLine = WhileType >> space >> Exp; 990 WhileLine = WhileType >> space >> Exp;
@@ -1001,11 +1041,16 @@ YueParser::YueParser() {
1001 empty_line_break | 1041 empty_line_break |
1002 advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) 1042 advance_match >> ensure(space >> (indentation_error | Statement), pop_indent)
1003 ); 1043 );
1004 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));
1005 1048
1006 shebang = "#!" >> *(not_(stop) >> any_char); 1049 shebang = "#!" >> *(not_(stop) >> any_char);
1007 BlockEnd = Block >> white >> stop; 1050 BlockEnd = Block >> white >> stop;
1008 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());
1009} 1054}
1010// clang-format on 1055// clang-format on
1011 1056
@@ -1035,7 +1080,7 @@ bool YueParser::startWith(std::string_view codes, rule& r) {
1035 return true; 1080 return true;
1036} 1081}
1037 1082
1038ParseInfo YueParser::parse(std::string_view codes, rule& r) { 1083ParseInfo YueParser::parse(std::string_view codes, rule& r, bool lax) {
1039 ParseInfo res; 1084 ParseInfo res;
1040 if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { 1085 if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) {
1041 codes = codes.substr(3); 1086 codes = codes.substr(3);
@@ -1053,6 +1098,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) {
1053 error_list errors; 1098 error_list errors;
1054 try { 1099 try {
1055 State state; 1100 State state;
1101 state.lax = lax;
1056 res.node.set(::yue::parse(*(res.codes), r, errors, &state)); 1102 res.node.set(::yue::parse(*(res.codes), r, errors, &state));
1057 if (state.exportCount > 0) { 1103 if (state.exportCount > 0) {
1058 int index = 0; 1104 int index = 0;
@@ -1090,19 +1136,21 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) {
1090 return res; 1136 return res;
1091} 1137}
1092 1138
1093ParseInfo YueParser::parse(std::string_view astName, std::string_view codes) { 1139ParseInfo YueParser::parse(std::string_view astName, std::string_view codes, bool lax) {
1094 auto it = _rules.find(astName); 1140 auto it = _rules.find(astName);
1095 if (it != _rules.end()) { 1141 if (it != _rules.end()) {
1096 return parse(codes, *it->second); 1142 return parse(codes, *it->second, lax);
1097 } 1143 }
1098 return {}; 1144 ParseInfo info{};
1145 info.error = ParseInfo::Error{"invalid rule: "s + std::string{astName}, 1, 1};
1146 return info;
1099} 1147}
1100 1148
1101bool YueParser::match(std::string_view astName, std::string_view codes) { 1149bool YueParser::match(std::string_view astName, std::string_view codes) {
1102 auto it = _rules.find(astName); 1150 auto it = _rules.find(astName);
1103 if (it != _rules.end()) { 1151 if (it != _rules.end()) {
1104 auto rEnd = rule(*it->second >> eof()); 1152 auto rEnd = rule(*it->second >> eof());
1105 return parse(codes, rEnd).node; 1153 return parse(codes, rEnd, false).node;
1106 } 1154 }
1107 return false; 1155 return false;
1108} 1156}
@@ -1138,6 +1186,24 @@ void trim(std::string& str) {
1138 str.erase(0, str.find_first_not_of(" \t\r\n")); 1186 str.erase(0, str.find_first_not_of(" \t\r\n"));
1139 str.erase(str.find_last_not_of(" \t\r\n") + 1); 1187 str.erase(str.find_last_not_of(" \t\r\n") + 1);
1140} 1188}
1189
1190std::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}
1141} // namespace Utils 1207} // namespace Utils
1142 1208
1143std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { 1209std::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 7281ec3..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;
74class YueParser { 74class YueParser {
75public: 75public:
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
103protected: 103protected:
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);
@@ -217,6 +219,8 @@ private:
217 NONE_AST_RULE(enable_for); 219 NONE_AST_RULE(enable_for);
218 NONE_AST_RULE(enable_fun_lit); 220 NONE_AST_RULE(enable_fun_lit);
219 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);
220 NONE_AST_RULE(switch_else); 224 NONE_AST_RULE(switch_else);
221 NONE_AST_RULE(switch_block); 225 NONE_AST_RULE(switch_block);
222 NONE_AST_RULE(if_else_if); 226 NONE_AST_RULE(if_else_if);
@@ -284,6 +288,7 @@ private:
284 NONE_AST_RULE(yue_line_comment); 288 NONE_AST_RULE(yue_line_comment);
285 NONE_AST_RULE(line); 289 NONE_AST_RULE(line);
286 NONE_AST_RULE(shebang); 290 NONE_AST_RULE(shebang);
291 NONE_AST_RULE(lax_line);
287 292
288 AST_RULE(Num); 293 AST_RULE(Num);
289 AST_RULE(Name); 294 AST_RULE(Name);
@@ -315,12 +320,14 @@ private:
315 AST_RULE(ImportAllMacro); 320 AST_RULE(ImportAllMacro);
316 AST_RULE(ImportTabLit); 321 AST_RULE(ImportTabLit);
317 AST_RULE(ImportAs); 322 AST_RULE(ImportAs);
323 AST_RULE(ImportGlobal);
318 AST_RULE(Import); 324 AST_RULE(Import);
319 AST_RULE(Label); 325 AST_RULE(Label);
320 AST_RULE(Goto); 326 AST_RULE(Goto);
321 AST_RULE(ShortTabAppending); 327 AST_RULE(ShortTabAppending);
322 AST_RULE(FnArrowBack); 328 AST_RULE(FnArrowBack);
323 AST_RULE(Backcall); 329 AST_RULE(Backcall);
330 AST_RULE(SubBackcall);
324 AST_RULE(PipeBody); 331 AST_RULE(PipeBody);
325 AST_RULE(ExpListLow); 332 AST_RULE(ExpListLow);
326 AST_RULE(ExpList); 333 AST_RULE(ExpList);
@@ -359,6 +366,7 @@ private:
359 AST_RULE(ExpOpValue); 366 AST_RULE(ExpOpValue);
360 AST_RULE(Exp); 367 AST_RULE(Exp);
361 AST_RULE(Callable); 368 AST_RULE(Callable);
369 AST_RULE(ReversedIndex);
362 AST_RULE(ChainValue); 370 AST_RULE(ChainValue);
363 AST_RULE(SimpleTable); 371 AST_RULE(SimpleTable);
364 AST_RULE(SimpleValue); 372 AST_RULE(SimpleValue);
@@ -371,6 +379,11 @@ private:
371 AST_RULE(DoubleStringInner); 379 AST_RULE(DoubleStringInner);
372 AST_RULE(DoubleStringContent); 380 AST_RULE(DoubleStringContent);
373 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);
374 AST_RULE(String); 387 AST_RULE(String);
375 AST_RULE(Parens); 388 AST_RULE(Parens);
376 AST_RULE(DotChainItem); 389 AST_RULE(DotChainItem);
@@ -427,6 +440,8 @@ private:
427 AST_RULE(ExpListAssign); 440 AST_RULE(ExpListAssign);
428 AST_RULE(IfLine); 441 AST_RULE(IfLine);
429 AST_RULE(WhileLine); 442 AST_RULE(WhileLine);
443 AST_RULE(Break);
444 AST_RULE(Continue);
430 AST_RULE(BreakLoop); 445 AST_RULE(BreakLoop);
431 AST_RULE(StatementAppendix); 446 AST_RULE(StatementAppendix);
432 AST_RULE(Statement); 447 AST_RULE(Statement);
@@ -444,6 +459,7 @@ private:
444namespace Utils { 459namespace Utils {
445void replace(std::string& str, std::string_view from, std::string_view to); 460void replace(std::string& str, std::string_view from, std::string_view to);
446void trim(std::string& str); 461void trim(std::string& str);
462std::string toLuaDoubleString(const std::string& input);
447} // namespace Utils 463} // namespace Utils
448 464
449} // 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>