diff options
Diffstat (limited to '')
63 files changed, 7374 insertions, 756 deletions
diff --git a/doc/docs/.vuepress/components/YueCompiler.vue b/doc/docs/.vuepress/components/YueCompiler.vue index 6b6042c..3a22d1c 100755 --- a/doc/docs/.vuepress/components/YueCompiler.vue +++ b/doc/docs/.vuepress/components/YueCompiler.vue | |||
@@ -1,21 +1,21 @@ | |||
1 | <template> | 1 | <template> |
2 | <div style="width: 100%; height: auto;"> | 2 | <div style="width: 100%; height: auto;"> |
3 | <div class="parent" style="background-color: #f5f7ff;"> | 3 | <div class="parent" style="background-color: #f5f7ff;"> |
4 | <div class="childL" style="height: 2.5em;"> | 4 | <div class="editor-section"> |
5 | <div class="childTitle">YueScript {{ info }}</div> | 5 | <div class="childTitle">YueScript {{ info }}</div> |
6 | <div class="editor-container" ref='yueEditor'> | ||
7 | <ClientOnly> | ||
8 | <prism-editor class="my-editor" v-model="code" :highlight="highlighterYue" @input="codeChanged($event)" line-numbers :readonly="readonly"></prism-editor> | ||
9 | </ClientOnly> | ||
10 | </div> | ||
6 | </div> | 11 | </div> |
7 | <div class="childR" style="height: 2.5em;"> | 12 | <div class="editor-section"> |
8 | <div class="childTitle">Lua</div> | 13 | <div class="childTitle">Lua</div> |
9 | </div> | 14 | <div class="editor-container"> |
10 | <div class="childL" ref='yueEditor' style="height: 30em;"> | 15 | <ClientOnly> |
11 | <ClientOnly> | 16 | <prism-editor class="my-editor" v-model="compiled" :highlight="highlighterLua" @input="codeChanged($event)" :line-numbers="isMobileLayout" readonly></prism-editor> |
12 | <prism-editor class="my-editor" v-model="code" :highlight="highlighterYue" @input="codeChanged($event)" line-numbers :readonly="readonly"></prism-editor> | 17 | </ClientOnly> |
13 | </ClientOnly> | 18 | </div> |
14 | </div> | ||
15 | <div class="childR" style="height: 30em;"> | ||
16 | <ClientOnly> | ||
17 | <prism-editor class="my-editor" v-model="compiled" :highlight="highlighterLua" @input="codeChanged($event)" readonly></prism-editor> | ||
18 | </ClientOnly> | ||
19 | </div> | 19 | </div> |
20 | </div> | 20 | </div> |
21 | <div v-if="!compileronly"> | 21 | <div v-if="!compileronly"> |
@@ -57,9 +57,18 @@ | |||
57 | code: '', | 57 | code: '', |
58 | compiled: '', | 58 | compiled: '', |
59 | result: '', | 59 | result: '', |
60 | windowWidth: 0, | ||
60 | }; | 61 | }; |
61 | }, | 62 | }, |
63 | computed: { | ||
64 | isMobileLayout() { | ||
65 | return this.windowWidth <= 768; | ||
66 | }, | ||
67 | }, | ||
62 | mounted () { | 68 | mounted () { |
69 | this.windowWidth = window.innerWidth; | ||
70 | window.addEventListener('resize', this.handleResize); | ||
71 | |||
63 | if (this.text !== '') { | 72 | if (this.text !== '') { |
64 | this.$data.code = this.text; | 73 | this.$data.code = this.text; |
65 | this.codeChanged(this.text); | 74 | this.codeChanged(this.text); |
@@ -86,7 +95,13 @@ | |||
86 | })(this); | 95 | })(this); |
87 | check(); | 96 | check(); |
88 | }, | 97 | }, |
98 | beforeDestroy() { | ||
99 | window.removeEventListener('resize', this.handleResize); | ||
100 | }, | ||
89 | methods: { | 101 | methods: { |
102 | handleResize() { | ||
103 | this.windowWidth = window.innerWidth; | ||
104 | }, | ||
90 | runCode() { | 105 | runCode() { |
91 | if (window.yue && this.$data.compiled !== '') { | 106 | if (window.yue && this.$data.compiled !== '') { |
92 | let res = ''; | 107 | let res = ''; |
@@ -136,27 +151,35 @@ | |||
136 | resize: none; | 151 | resize: none; |
137 | margin-top: 5px; | 152 | margin-top: 5px; |
138 | } | 153 | } |
139 | .childL { | 154 | |
140 | float: left; | 155 | .parent { |
141 | width: 50%; | 156 | display: flex; |
142 | box-sizing: border-box; | 157 | flex-wrap: wrap; |
143 | background-clip: content-box; | 158 | width: 100%; |
144 | background: #f5f7ff; | ||
145 | } | 159 | } |
146 | .childR { | 160 | |
147 | float: left; | 161 | .editor-section { |
148 | width: 50%; | 162 | width: 50%; |
149 | box-sizing: border-box; | 163 | box-sizing: border-box; |
150 | background-clip: content-box; | ||
151 | background: #f5f7ff; | 164 | background: #f5f7ff; |
152 | } | 165 | } |
166 | |||
167 | .editor-container { | ||
168 | height: 55vh; | ||
169 | } | ||
170 | |||
153 | .childTitle { | 171 | .childTitle { |
154 | width: 100%; | 172 | width: 100%; |
155 | font-size: 1.2em; | 173 | font-size: 1.2em; |
156 | color: #b7ae8f; | 174 | color: #b7ae8f; |
157 | text-align: center; | 175 | text-align: center; |
158 | padding: 0.2em; | 176 | padding: 0.2em; |
177 | height: 2.5em; | ||
178 | display: flex; | ||
179 | align-items: center; | ||
180 | justify-content: center; | ||
159 | } | 181 | } |
182 | |||
160 | .button { | 183 | .button { |
161 | float: right; | 184 | float: right; |
162 | border: none; | 185 | border: none; |
@@ -173,9 +196,11 @@ | |||
173 | margin-top: 10px; | 196 | margin-top: 10px; |
174 | margin-right: 5px; | 197 | margin-right: 5px; |
175 | } | 198 | } |
199 | |||
176 | .button:hover { | 200 | .button:hover { |
177 | background-color: #beb69a; | 201 | background-color: #beb69a; |
178 | } | 202 | } |
203 | |||
179 | .button:focus, | 204 | .button:focus, |
180 | .button:active:focus, | 205 | .button:active:focus, |
181 | .button.active:focus, | 206 | .button.active:focus, |
@@ -207,5 +232,19 @@ | |||
207 | .my-editor >>> .prism-editor__textarea:focus { | 232 | .my-editor >>> .prism-editor__textarea:focus { |
208 | outline: none; | 233 | outline: none; |
209 | } | 234 | } |
210 | </style> | ||
211 | 235 | ||
236 | /* 移动端å“应å¼å¸ƒå±€ */ | ||
237 | @media screen and (max-width: 768px) { | ||
238 | .parent { | ||
239 | flex-direction: column; | ||
240 | } | ||
241 | |||
242 | .editor-section { | ||
243 | width: 100%; | ||
244 | } | ||
245 | |||
246 | .editor-container { | ||
247 | height: 30vh; | ||
248 | } | ||
249 | } | ||
250 | </style> | ||
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md index c4518bf..57f27c8 100755 --- a/doc/docs/doc/README.md +++ b/doc/docs/doc/README.md | |||
@@ -16,19 +16,29 @@ Yue (月) is the name of moon in Chinese and it's pronounced as [jyɛ]. | |||
16 | ### An Overview of YueScript | 16 | ### An Overview of YueScript |
17 | ```moonscript | 17 | ```moonscript |
18 | -- import syntax | 18 | -- import syntax |
19 | import "yue" as :p, :to_lua | 19 | import p, to_lua from "yue" |
20 | 20 | ||
21 | -- object literals | 21 | -- object literals |
22 | inventory = | 22 | inventory = |
23 | equipment: | 23 | equipment: |
24 | * "sword" | 24 | - "sword" |
25 | * "shield" | 25 | - "shield" |
26 | items: | 26 | items: |
27 | * name: "potion" | 27 | - name: "potion" |
28 | count: 10 | 28 | count: 10 |
29 | * name: "bread" | 29 | - name: "bread" |
30 | count: 3 | 30 | count: 3 |
31 | 31 | ||
32 | -- list comprehension | ||
33 | map = (arr, action) -> | ||
34 | [action item for item in *arr] | ||
35 | |||
36 | filter = (arr, cond) -> | ||
37 | [item for item in *arr when cond item] | ||
38 | |||
39 | reduce = (arr, init, action): init -> | ||
40 | init = action init, item for item in *arr | ||
41 | |||
32 | -- pipe operator | 42 | -- pipe operator |
33 | [1, 2, 3] | 43 | [1, 2, 3] |
34 | |> map (x) -> x * 2 | 44 | |> map (x) -> x * 2 |
@@ -51,19 +61,29 @@ export 🌛 = "月之脚本" | |||
51 | <YueDisplay> | 61 | <YueDisplay> |
52 | <pre> | 62 | <pre> |
53 | -- import syntax | 63 | -- import syntax |
54 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
55 | 65 | ||
56 | -- object literals | 66 | -- object literals |
57 | inventory = | 67 | inventory = |
58 | equipment: | 68 | equipment: |
59 | * "sword" | 69 | - "sword" |
60 | * "shield" | 70 | - "shield" |
61 | items: | 71 | items: |
62 | * name: "potion" | 72 | - name: "potion" |
63 | count: 10 | 73 | count: 10 |
64 | * name: "bread" | 74 | - name: "bread" |
65 | count: 3 | 75 | count: 3 |
66 | 76 | ||
77 | -- list comprehension | ||
78 | map = (arr, action) -> | ||
79 | [action item for item in *arr] | ||
80 | |||
81 | filter = (arr, cond) -> | ||
82 | [item for item in *arr when cond item] | ||
83 | |||
84 | reduce = (arr, init, action): init -> | ||
85 | init = action init, item for item in *arr | ||
86 | |||
67 | -- pipe operator | 87 | -- pipe operator |
68 | [1, 2, 3] | 88 | [1, 2, 3] |
69 | |> map (x) -> x * 2 | 89 | |> map (x) -> x * 2 |
@@ -132,14 +152,14 @@ export 🌛 = "月之脚本" | |||
132 | 152 | ||
133 |  Use YueScript module in Lua: | 153 |  Use YueScript module in Lua: |
134 | 154 | ||
135 | * **Case 1** | 155 | * **Case 1** |
136 | Require "your_yuescript_entry.yue" in Lua. | 156 | Require "your_yuescript_entry.yue" in Lua. |
137 | ```Lua | 157 | ```Lua |
138 | require("yue")("your_yuescript_entry") | 158 | require("yue")("your_yuescript_entry") |
139 | ``` | 159 | ``` |
140 |  And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. | 160 |  And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. |
141 | 161 | ||
142 | * **Case 2** | 162 | * **Case 2** |
143 | Require YueScript module and rewite message by hand. | 163 | Require YueScript module and rewite message by hand. |
144 | ```lua | 164 | ```lua |
145 | local yue = require("yue") | 165 | local yue = require("yue") |
@@ -151,7 +171,7 @@ end, function(err) | |||
151 | end) | 171 | end) |
152 | ``` | 172 | ``` |
153 | 173 | ||
154 | * **Case 3** | 174 | * **Case 3** |
155 | Use the YueScript compiler function in Lua. | 175 | Use the YueScript compiler function in Lua. |
156 | ```lua | 176 | ```lua |
157 | local yue = require("yue") | 177 | local yue = require("yue") |
@@ -203,12 +223,12 @@ Usage: yue [options|files|directories] ... | |||
203 | Execute without options to enter REPL, type symbol '$' | 223 | Execute without options to enter REPL, type symbol '$' |
204 | in a single line to start/stop multi-line mode | 224 | in a single line to start/stop multi-line mode |
205 | ``` | 225 | ``` |
206 |   Use cases: | 226 |   Use cases: |
207 |   Recursively compile every YueScript file with extension **.yue** under current path: **yue .** | 227 |   Recursively compile every YueScript file with extension **.yue** under current path: **yue .** |
208 |   Compile and save results to a target path: **yue -t /target/path/ .** | 228 |   Compile and save results to a target path: **yue -t /target/path/ .** |
209 |   Compile and reserve debug info: **yue -l .** | 229 |   Compile and reserve debug info: **yue -l .** |
210 |   Compile and generate minified codes: **yue -m .** | 230 |   Compile and generate minified codes: **yue -m .** |
211 |   Execute raw codes: **yue -e 'print 123'** | 231 |   Execute raw codes: **yue -e 'print 123'** |
212 |   Execute a YueScript file: **yue -e main.yue** | 232 |   Execute a YueScript file: **yue -e main.yue** |
213 | 233 | ||
214 | ## Macro | 234 | ## Macro |
@@ -424,6 +444,54 @@ print "Valid enum type:", $BodyType Static | |||
424 | </pre> | 444 | </pre> |
425 | </YueDisplay> | 445 | </YueDisplay> |
426 | 446 | ||
447 | ### Argument Validation | ||
448 | |||
449 | You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time. | ||
450 | |||
451 | ```moonscript | ||
452 | macro printNumAndStr = (num `Num, str `String) -> | | ||
453 | print( | ||
454 | #{num} | ||
455 | #{str} | ||
456 | ) | ||
457 | |||
458 | $printNumAndStr 123, "hello" | ||
459 | ``` | ||
460 | <YueDisplay> | ||
461 | <pre> | ||
462 | macro printNumAndStr = (num `Num, str `String) -> | | ||
463 | print( | ||
464 | #{num} | ||
465 | #{str} | ||
466 | ) | ||
467 | |||
468 | $printNumAndStr 123, "hello" | ||
469 | </pre> | ||
470 | </YueDisplay> | ||
471 | |||
472 | If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place. | ||
473 | |||
474 | ```moonscript | ||
475 | macro printNumAndStr = (num, str) -> | ||
476 | error "expected Num as first argument" unless $is_ast Num, num | ||
477 | error "expected String as second argument" unless $is_ast String, str | ||
478 | "print(#{num}, #{str})" | ||
479 | |||
480 | $printNumAndStr 123, "hello" | ||
481 | ``` | ||
482 | <YueDisplay> | ||
483 | <pre> | ||
484 | macro printNumAndStr = (num, str) -> | ||
485 | error "expected Num as first argument" unless $is_ast Num, num | ||
486 | error "expected String as second argument" unless $is_ast String, str | ||
487 | "print(#{num}, #{str})" | ||
488 | |||
489 | $printNumAndStr 123, "hello" | ||
490 | </pre> | ||
491 | </YueDisplay> | ||
492 | |||
493 | For more details about available AST nodes, please refer to the uppercased definitions in [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp). | ||
494 | |||
427 | ## Operator | 495 | ## Operator |
428 | 496 | ||
429 | All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. | 497 | All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. |
@@ -566,11 +634,26 @@ merge = {...a, ...b} | |||
566 | </pre> | 634 | </pre> |
567 | </YueDisplay> | 635 | </YueDisplay> |
568 | 636 | ||
637 | ### Table Reversed Indexing | ||
638 | |||
639 | You can use the **#** operator to get the last elements of a table. | ||
640 | |||
641 | ```moonscript | ||
642 | last = data.items[#] | ||
643 | second_last = data.items[#-1] | ||
644 | ``` | ||
645 | <YueDisplay> | ||
646 | <pre> | ||
647 | last = data.items[#] | ||
648 | second_last = data.items[#-1] | ||
649 | </pre> | ||
650 | </YueDisplay> | ||
651 | |||
569 | ### Metatable | 652 | ### Metatable |
570 | 653 | ||
571 | The **<>** operator can be used as a shortcut for metatable manipulation. | 654 | The **<>** operator can be used as a shortcut for metatable manipulation. |
572 | 655 | ||
573 | * **Metatable Creation** | 656 | * **Metatable Creation** |
574 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. | 657 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. |
575 | 658 | ||
576 | ```moonscript | 659 | ```moonscript |
@@ -606,7 +689,7 @@ close _ = <close>: -> print "out of scope" | |||
606 | </pre> | 689 | </pre> |
607 | </YueDisplay> | 690 | </YueDisplay> |
608 | 691 | ||
609 | * **Metatable Accessing** | 692 | * **Metatable Accessing** |
610 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. | 693 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. |
611 | 694 | ||
612 | ```moonscript | 695 | ```moonscript |
@@ -630,7 +713,7 @@ print tb.item | |||
630 | </pre> | 713 | </pre> |
631 | </YueDisplay> | 714 | </YueDisplay> |
632 | 715 | ||
633 | * **Metatable Destructure** | 716 | * **Metatable Destructure** |
634 | Destruct metatable with metamethod key surrounded by **<>**. | 717 | Destruct metatable with metamethod key surrounded by **<>**. |
635 | 718 | ||
636 | ```moonscript | 719 | ```moonscript |
@@ -732,34 +815,45 @@ a ??= false | |||
732 | 815 | ||
733 | ### Implicit Object | 816 | ### Implicit Object |
734 | 817 | ||
735 | You can write a list of implicit structures that starts with the symbol **\*** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. | 818 | You can write a list of implicit structures that starts with the symbol **\*** or **-** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. |
819 | |||
736 | ```moonscript | 820 | ```moonscript |
821 | -- assignment with implicit object | ||
737 | list = | 822 | list = |
738 | * 1 | 823 | * 1 |
739 | * 2 | 824 | * 2 |
740 | * 3 | 825 | * 3 |
741 | 826 | ||
827 | -- function call with implicit object | ||
742 | func | 828 | func |
743 | * 1 | 829 | * 1 |
744 | * 2 | 830 | * 2 |
745 | * 3 | 831 | * 3 |
746 | 832 | ||
833 | -- return with implicit object | ||
834 | f = -> | ||
835 | return | ||
836 | * 1 | ||
837 | * 2 | ||
838 | * 3 | ||
839 | |||
840 | -- table with implicit object | ||
747 | tb = | 841 | tb = |
748 | name: "abc" | 842 | name: "abc" |
749 | 843 | ||
750 | values: | 844 | values: |
751 | * "a" | 845 | - "a" |
752 | * "b" | 846 | - "b" |
753 | * "c" | 847 | - "c" |
754 | 848 | ||
755 | objects: | 849 | objects: |
756 | * name: "a" | 850 | - name: "a" |
757 | value: 1 | 851 | value: 1 |
758 | func: => @value + 1 | 852 | func: => @value + 1 |
759 | tb: | 853 | tb: |
760 | fieldA: 1 | 854 | fieldA: 1 |
761 | 855 | ||
762 | * name: "b" | 856 | - name: "b" |
763 | value: 2 | 857 | value: 2 |
764 | func: => @value + 2 | 858 | func: => @value + 2 |
765 | tb: { } | 859 | tb: { } |
@@ -767,32 +861,42 @@ tb = | |||
767 | ``` | 861 | ``` |
768 | <YueDisplay> | 862 | <YueDisplay> |
769 | <pre> | 863 | <pre> |
864 | -- assignment with implicit object | ||
770 | list = | 865 | list = |
771 | * 1 | 866 | * 1 |
772 | * 2 | 867 | * 2 |
773 | * 3 | 868 | * 3 |
774 | 869 | ||
870 | -- function call with implicit object | ||
775 | func | 871 | func |
776 | * 1 | 872 | * 1 |
777 | * 2 | 873 | * 2 |
778 | * 3 | 874 | * 3 |
779 | 875 | ||
876 | -- return with implicit object | ||
877 | f = -> | ||
878 | return | ||
879 | * 1 | ||
880 | * 2 | ||
881 | * 3 | ||
882 | |||
883 | -- table with implicit object | ||
780 | tb = | 884 | tb = |
781 | name: "abc" | 885 | name: "abc" |
782 | 886 | ||
783 | values: | 887 | values: |
784 | * "a" | 888 | - "a" |
785 | * "b" | 889 | - "b" |
786 | * "c" | 890 | - "c" |
787 | 891 | ||
788 | objects: | 892 | objects: |
789 | * name: "a" | 893 | - name: "a" |
790 | value: 1 | 894 | value: 1 |
791 | func: => @value + 1 | 895 | func: => @value + 1 |
792 | tb: | 896 | tb: |
793 | fieldA: 1 | 897 | fieldA: 1 |
794 | 898 | ||
795 | * name: "b" | 899 | - name: "b" |
796 | value: 2 | 900 | value: 2 |
797 | func: => @value + 2 | 901 | func: => @value + 2 |
798 | tb: { } | 902 | tb: { } |
@@ -860,7 +964,7 @@ do | |||
860 | 964 | ||
861 | The export statement offers a concise way to define modules. | 965 | The export statement offers a concise way to define modules. |
862 | 966 | ||
863 | * **Named Export** | 967 | * **Named Export** |
864 | Named export will define a local variable as well as adding a field in the exported table. | 968 | Named export will define a local variable as well as adding a field in the exported table. |
865 | 969 | ||
866 | ```moonscript | 970 | ```moonscript |
@@ -924,7 +1028,7 @@ export["a-b-c"] = 123 | |||
924 | </pre> | 1028 | </pre> |
925 | </YueDisplay> | 1029 | </YueDisplay> |
926 | 1030 | ||
927 | * **Unnamed Export** | 1031 | * **Unnamed Export** |
928 | Unnamed export will add the target item into the array part of the exported table. | 1032 | Unnamed export will add the target item into the array part of the exported table. |
929 | 1033 | ||
930 | ```moonscript | 1034 | ```moonscript |
@@ -954,7 +1058,7 @@ export with tmp | |||
954 | </pre> | 1058 | </pre> |
955 | </YueDisplay> | 1059 | </YueDisplay> |
956 | 1060 | ||
957 | * **Default Export** | 1061 | * **Default Export** |
958 | Using the **default** keyword in export statement to replace the exported table with any thing. | 1062 | Using the **default** keyword in export statement to replace the exported table with any thing. |
959 | 1063 | ||
960 | ```moonscript | 1064 | ```moonscript |
@@ -1202,7 +1306,7 @@ If the destructuring statement is complicated, feel free to spread it out over a | |||
1202 | </pre> | 1306 | </pre> |
1203 | </YueDisplay> | 1307 | </YueDisplay> |
1204 | 1308 | ||
1205 | It’s common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: | 1309 | It's common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: |
1206 | 1310 | ||
1207 | ```moonscript | 1311 | ```moonscript |
1208 | {:concat, :insert} = table | 1312 | {:concat, :insert} = table |
@@ -1246,6 +1350,52 @@ You can use `_` as placeholder when doing a list destructuring: | |||
1246 | </pre> | 1350 | </pre> |
1247 | </YueDisplay> | 1351 | </YueDisplay> |
1248 | 1352 | ||
1353 | ### Range Destructuring | ||
1354 | |||
1355 | You can use the spread operator `...` in list destructuring to capture a range of values. This is useful when you want to extract specific elements from the beginning and end of a list while collecting the rest in between. | ||
1356 | |||
1357 | ```moonscript | ||
1358 | orders = ["first", "second", "third", "fourth", "last"] | ||
1359 | [first, ...bulk, last] = orders | ||
1360 | print first -- prints: first | ||
1361 | print bulk -- prints: {"second", "third", "fourth"} | ||
1362 | print last -- prints: last | ||
1363 | ``` | ||
1364 | <YueDisplay> | ||
1365 | <pre> | ||
1366 | orders = ["first", "second", "third", "fourth", "last"] | ||
1367 | [first, ...bulk, last] = orders | ||
1368 | print first -- prints: first | ||
1369 | print bulk -- prints: {"second", "third", "fourth"} | ||
1370 | print last -- prints: last | ||
1371 | </pre> | ||
1372 | </YueDisplay> | ||
1373 | |||
1374 | The spread operator can be used in different positions to capture different ranges, and you can use `_` as a placeholder for the values you don't want to capture: | ||
1375 | |||
1376 | ```moonscript | ||
1377 | -- Capture everything after first element | ||
1378 | [first, ...rest] = orders | ||
1379 | |||
1380 | -- Capture everything before last element | ||
1381 | [...start, last] = orders | ||
1382 | |||
1383 | -- Capture things except the middle elements | ||
1384 | [first, ..._, last] = orders | ||
1385 | ``` | ||
1386 | <YueDisplay> | ||
1387 | <pre> | ||
1388 | -- Capture everything after first element | ||
1389 | [first, ...rest] = orders | ||
1390 | |||
1391 | -- Capture everything before last element | ||
1392 | [...start, last] = orders | ||
1393 | |||
1394 | -- Capture things except the middle elements | ||
1395 | [first, ..._, last] = orders | ||
1396 | </pre> | ||
1397 | </YueDisplay> | ||
1398 | |||
1249 | ### Destructuring In Other Places | 1399 | ### Destructuring In Other Places |
1250 | 1400 | ||
1251 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: | 1401 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: |
@@ -1475,6 +1625,47 @@ catch err | |||
1475 | </pre> | 1625 | </pre> |
1476 | </YueDisplay> | 1626 | </YueDisplay> |
1477 | 1627 | ||
1628 | ### Try? | ||
1629 | |||
1630 | `try?` is a simplified use for error handling syntax that omit the boolean status from the `try` statement, and it will return the result from the try block when success, return nil instead of error object otherwise. | ||
1631 | |||
1632 | ```moonscript | ||
1633 | a, b, c = try? func! | ||
1634 | |||
1635 | -- with nil coalescing operator | ||
1636 | a = (try? func!) ?? "default" | ||
1637 | |||
1638 | -- as function argument | ||
1639 | f try? func! | ||
1640 | |||
1641 | -- with catch block | ||
1642 | f try? | ||
1643 | print 123 | ||
1644 | func! | ||
1645 | catch e | ||
1646 | print e | ||
1647 | e | ||
1648 | ``` | ||
1649 | <YueDisplay> | ||
1650 | <pre> | ||
1651 | a, b, c = try? func! | ||
1652 | |||
1653 | -- with nil coalescing operator | ||
1654 | a = (try? func!) ?? "default" | ||
1655 | |||
1656 | -- as function argument | ||
1657 | f try? func! | ||
1658 | |||
1659 | -- with catch block | ||
1660 | f try? | ||
1661 | print 123 | ||
1662 | func! | ||
1663 | catch e | ||
1664 | print e | ||
1665 | e | ||
1666 | </pre> | ||
1667 | </YueDisplay> | ||
1668 | |||
1478 | ## Attributes | 1669 | ## Attributes |
1479 | 1670 | ||
1480 | Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. | 1671 | Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. |
@@ -1503,6 +1694,19 @@ const {:a, :b, c, d} = tb | |||
1503 | </pre> | 1694 | </pre> |
1504 | </YueDisplay> | 1695 | </YueDisplay> |
1505 | 1696 | ||
1697 | You can also declare a global variable to be `const`. | ||
1698 | |||
1699 | ```moonscript | ||
1700 | global const Constant = 123 | ||
1701 | -- Constant = 1 | ||
1702 | ``` | ||
1703 | <YueDisplay> | ||
1704 | <pre> | ||
1705 | global const Constant = 123 | ||
1706 | -- Constant = 1 | ||
1707 | </pre> | ||
1708 | </YueDisplay> | ||
1709 | |||
1506 | ## Literals | 1710 | ## Literals |
1507 | 1711 | ||
1508 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. | 1712 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. |
@@ -1535,12 +1739,73 @@ You can use underscores in a number literal to increase readability. | |||
1535 | ```moonscript | 1739 | ```moonscript |
1536 | integer = 1_000_000 | 1740 | integer = 1_000_000 |
1537 | hex = 0xEF_BB_BF | 1741 | hex = 0xEF_BB_BF |
1742 | binary = 0B10011 | ||
1538 | ``` | 1743 | ``` |
1539 | <YueDisplay> | 1744 | <YueDisplay> |
1540 | 1745 | ||
1541 | <pre> | 1746 | <pre> |
1542 | integer = 1_000_000 | 1747 | integer = 1_000_000 |
1543 | hex = 0xEF_BB_BF | 1748 | hex = 0xEF_BB_BF |
1749 | binary = 0B10011 | ||
1750 | </pre> | ||
1751 | </YueDisplay> | ||
1752 | |||
1753 | ### YAML Multiline String | ||
1754 | |||
1755 | The `|` prefix introduces a YAML-style multiline string literal: | ||
1756 | |||
1757 | ```moonscript | ||
1758 | str = | | ||
1759 | key: value | ||
1760 | list: | ||
1761 | - item1 | ||
1762 | - #{expr} | ||
1763 | ``` | ||
1764 | <YueDisplay> | ||
1765 | <pre> | ||
1766 | str = | | ||
1767 | key: value | ||
1768 | list: | ||
1769 | - item1 | ||
1770 | - #{expr} | ||
1771 | </pre> | ||
1772 | </YueDisplay> | ||
1773 | |||
1774 | This allows writing structured multiline text conveniently. All line breaks and indentation are preserved relative to the first non-empty line, and expressions inside `#{...}` are interpolated automatically as `tostring(expr)`. | ||
1775 | |||
1776 | YAML Multiline String automatically detects the common leading whitespace prefix (minimum indentation across all non-empty lines) and removes it from all lines. This makes it easy to indent your code visually without affecting the resulting string content. | ||
1777 | |||
1778 | ```moonscript | ||
1779 | fn = -> | ||
1780 | str = | | ||
1781 | foo: | ||
1782 | bar: baz | ||
1783 | return str | ||
1784 | ``` | ||
1785 | <YueDisplay> | ||
1786 | <pre> | ||
1787 | fn = -> | ||
1788 | str = | | ||
1789 | foo: | ||
1790 | bar: baz | ||
1791 | return str | ||
1792 | </pre> | ||
1793 | </YueDisplay> | ||
1794 | |||
1795 | Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures. | ||
1796 | |||
1797 | All special characters like quotes (`"`) and backslashes (`\`) in the YAMLMultiline block are automatically escaped so that the generated Lua string is syntactically valid and behaves as expected. | ||
1798 | |||
1799 | ```moonscript | ||
1800 | str = | | ||
1801 | path: "C:\Program Files\App" | ||
1802 | note: 'He said: "#{Hello}!"' | ||
1803 | ``` | ||
1804 | <YueDisplay> | ||
1805 | <pre> | ||
1806 | str = | | ||
1807 | path: "C:\Program Files\App" | ||
1808 | note: 'He said: "#{Hello}!"' | ||
1544 | </pre> | 1809 | </pre> |
1545 | </YueDisplay> | 1810 | </YueDisplay> |
1546 | 1811 | ||
@@ -1861,6 +2126,89 @@ if func 1, 2, 3, | |||
1861 | </pre> | 2126 | </pre> |
1862 | </YueDisplay> | 2127 | </YueDisplay> |
1863 | 2128 | ||
2129 | ### Parameter Destructuring | ||
2130 | |||
2131 | YueScript now supports destructuring function parameters when the argument is an object. Two forms of destructuring table literals are available: | ||
2132 | |||
2133 | * **Curly-brace wrapped literals/object parameters**, allowing optional default values when fields are missing (e.g., `{:a, :b}`, `{a: a1 = 123}`). | ||
2134 | |||
2135 | * **Unwrapped simple table syntax**, starting with a sequence of key-value or shorthand bindings and continuing until another expression terminates it (e.g., `:a, b: b1, :c`). This form extracts multiple fields from the same object. | ||
2136 | |||
2137 | ```moonscript | ||
2138 | f1 = (:a, :b, :c) -> | ||
2139 | print a, b, c | ||
2140 | |||
2141 | f1 a: 1, b: "2", c: {} | ||
2142 | |||
2143 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
2144 | print a1, b, c | ||
2145 | |||
2146 | arg1 = {a: 0} | ||
2147 | f2 arg1, arg2 | ||
2148 | ``` | ||
2149 | <YueDisplay> | ||
2150 | <pre> | ||
2151 | f1 = (:a, :b, :c) -> | ||
2152 | print a, b, c | ||
2153 | |||
2154 | f1 a: 1, b: "2", c: {} | ||
2155 | |||
2156 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
2157 | print a1, b, c | ||
2158 | |||
2159 | arg1 = {a: 0} | ||
2160 | f2 arg1, arg2 | ||
2161 | </pre> | ||
2162 | </YueDisplay> | ||
2163 | |||
2164 | ### Prefixed Return Expression | ||
2165 | |||
2166 | When working with deeply nested function bodies, it can be tedious to maintain readability and consistency of the return value. To address this, YueScript introduces the **Prefixed Return Expression** syntax. Its form is as follows: | ||
2167 | |||
2168 | ```moon | ||
2169 | findFirstEven = (list): nil -> | ||
2170 | for item in *list | ||
2171 | if type(item) == "table" | ||
2172 | for sub in *item | ||
2173 | if sub % 2 == 0 | ||
2174 | return sub | ||
2175 | ``` | ||
2176 | <YueDisplay> | ||
2177 | <pre> | ||
2178 | findFirstEven = (list): nil -> | ||
2179 | for item in *list | ||
2180 | if type(item) == "table" | ||
2181 | for sub in *item | ||
2182 | if sub % 2 == 0 | ||
2183 | return sub | ||
2184 | </pre> | ||
2185 | </YueDisplay> | ||
2186 | |||
2187 | This is equivalent to: | ||
2188 | |||
2189 | ```moon | ||
2190 | findFirstEven = (list) -> | ||
2191 | for item in *list | ||
2192 | if type(item) == "table" | ||
2193 | for sub in *item | ||
2194 | if sub % 2 == 0 | ||
2195 | return sub | ||
2196 | nil | ||
2197 | ``` | ||
2198 | <YueDisplay> | ||
2199 | <pre> | ||
2200 | findFirstEven = (list) -> | ||
2201 | for item in *list | ||
2202 | if type(item) == "table" | ||
2203 | for sub in *item | ||
2204 | if sub % 2 == 0 | ||
2205 | return sub | ||
2206 | nil | ||
2207 | </pre> | ||
2208 | </YueDisplay> | ||
2209 | |||
2210 | The only difference is that you can move the final return expression before the `->` or `=>` token to indicate the function’s implicit return value as the last statement. This way, even in functions with multiple nested loops or conditional branches, you no longer need to write a trailing return expression at the end of the function body, making the logic structure more straightforward and easier to follow. | ||
2211 | |||
1864 | ## Backcalls | 2212 | ## Backcalls |
1865 | 2213 | ||
1866 | Backcalls are used for unnesting callbacks. They are defined using arrows pointed to the left as the last parameter by default filling in a function call. All the syntax is mostly the same as regular arrow functions except that it is just pointing the other way and the function body does not require indent. | 2214 | Backcalls are used for unnesting callbacks. They are defined using arrows pointed to the left as the last parameter by default filling in a function call. All the syntax is mostly the same as regular arrow functions except that it is just pointing the other way and the function body does not require indent. |
@@ -1902,22 +2250,22 @@ x * 2 | |||
1902 | </pre> | 2250 | </pre> |
1903 | </YueDisplay> | 2251 | </YueDisplay> |
1904 | 2252 | ||
1905 | If you wish to have further code after your backcalls, you can set them aside with a do statement. | 2253 | If you wish to have further code after your backcalls, you can set them aside with a do statement. And the parentheses can be omitted with non-fat arrow functions. |
1906 | 2254 | ||
1907 | ```moonscript | 2255 | ```moonscript |
1908 | result, msg = do | 2256 | result, msg = do |
1909 | (data) <- readAsync "filename.txt" | 2257 | data <- readAsync "filename.txt" |
1910 | print data | 2258 | print data |
1911 | (info) <- processAsync data | 2259 | info <- processAsync data |
1912 | check info | 2260 | check info |
1913 | print result, msg | 2261 | print result, msg |
1914 | ``` | 2262 | ``` |
1915 | <YueDisplay> | 2263 | <YueDisplay> |
1916 | <pre> | 2264 | <pre> |
1917 | result, msg = do | 2265 | result, msg = do |
1918 | (data) <- readAsync "filename.txt" | 2266 | data <- readAsync "filename.txt" |
1919 | print data | 2267 | print data |
1920 | (info) <- processAsync data | 2268 | info <- processAsync data |
1921 | check info | 2269 | check info |
1922 | print result, msg | 2270 | print result, msg |
1923 | </pre> | 2271 | </pre> |
@@ -2248,6 +2596,45 @@ slice = [item for item in *items[,,2]] | |||
2248 | </pre> | 2596 | </pre> |
2249 | </YueDisplay> | 2597 | </YueDisplay> |
2250 | 2598 | ||
2599 | Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table. | ||
2600 | |||
2601 | ```moonscript | ||
2602 | -- take the last 4 items | ||
2603 | slice = [item for item in *items[-4,-1]] | ||
2604 | ``` | ||
2605 | <YueDisplay> | ||
2606 | <pre> | ||
2607 | -- take the last 4 items | ||
2608 | slice = [item for item in *items[-4,-1]] | ||
2609 | </pre> | ||
2610 | </YueDisplay> | ||
2611 | |||
2612 | The step size can also be negative, which means that the items are taken in reverse order. | ||
2613 | |||
2614 | ```moonscript | ||
2615 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2616 | ``` | ||
2617 | <YueDisplay> | ||
2618 | <pre> | ||
2619 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2620 | </pre> | ||
2621 | </YueDisplay> | ||
2622 | |||
2623 | #### Slicing Expression | ||
2624 | |||
2625 | Slicing can also be used as an expression. This is useful for getting a sub-list of a table. | ||
2626 | |||
2627 | ```moonscript | ||
2628 | -- take the 2nd and 4th items as a new list | ||
2629 | sub_list = items[2, 4] | ||
2630 | ``` | ||
2631 | <YueDisplay> | ||
2632 | <pre> | ||
2633 | -- take the 2nd and 4th items as a new list | ||
2634 | sub_list = items[2, 4] | ||
2635 | </pre> | ||
2636 | </YueDisplay> | ||
2637 | |||
2251 | ## For Loop | 2638 | ## For Loop |
2252 | 2639 | ||
2253 | There are two for loop forms, just like in Lua. A numeric one and a generic one: | 2640 | There are two for loop forms, just like in Lua. A numeric one and a generic one: |
@@ -2324,6 +2711,23 @@ doubled_evens = for i = 1, 20 | |||
2324 | </pre> | 2711 | </pre> |
2325 | </YueDisplay> | 2712 | </YueDisplay> |
2326 | 2713 | ||
2714 | In addition, for loops support break with a return value, allowing the loop itself to be used as an expression that exits early with a meaningful result. | ||
2715 | |||
2716 | For example, to find the first number greater than 10: | ||
2717 | |||
2718 | ```moonscript | ||
2719 | first_large = for n in *numbers | ||
2720 | break n if n > 10 | ||
2721 | ``` | ||
2722 | <YueDisplay> | ||
2723 | <pre> | ||
2724 | first_large = for n in *numbers | ||
2725 | break n if n > 10 | ||
2726 | </pre> | ||
2727 | </YueDisplay> | ||
2728 | |||
2729 | This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions. | ||
2730 | |||
2327 | You can also filter values by combining the for loop expression with the continue statement. | 2731 | You can also filter values by combining the for loop expression with the continue statement. |
2328 | 2732 | ||
2329 | For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. | 2733 | For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. |
@@ -2345,7 +2749,7 @@ print func_b! -- prints table object | |||
2345 | </pre> | 2749 | </pre> |
2346 | </YueDisplay> | 2750 | </YueDisplay> |
2347 | 2751 | ||
2348 | This is done to avoid the needless creation of tables for functions that don’t need to return the results of the loop. | 2752 | This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop. |
2349 | 2753 | ||
2350 | ## Repeat Loop | 2754 | ## Repeat Loop |
2351 | 2755 | ||
@@ -2624,28 +3028,26 @@ reader\parse_line! until reader\eof! | |||
2624 | 3028 | ||
2625 | ## Switch | 3029 | ## Switch |
2626 | 3030 | ||
2627 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. | 3031 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. In switch statement, you can also use assignment expression to store temporary variable value. |
2628 | 3032 | ||
2629 | ```moonscript | 3033 | ```moonscript |
2630 | name = "Dan" | 3034 | switch name := "Dan" |
2631 | switch name | ||
2632 | when "Robert" | 3035 | when "Robert" |
2633 | print "You are Robert" | 3036 | print "You are Robert" |
2634 | when "Dan", "Daniel" | 3037 | when "Dan", "Daniel" |
2635 | print "Your name, it's Dan" | 3038 | print "Your name, it's Dan" |
2636 | else | 3039 | else |
2637 | print "I don't know about your name" | 3040 | print "I don't know about you with name #{name}" |
2638 | ``` | 3041 | ``` |
2639 | <YueDisplay> | 3042 | <YueDisplay> |
2640 | <pre> | 3043 | <pre> |
2641 | name = "Dan" | 3044 | switch name := "Dan" |
2642 | switch name | ||
2643 | when "Robert" | 3045 | when "Robert" |
2644 | print "You are Robert" | 3046 | print "You are Robert" |
2645 | when "Dan", "Daniel" | 3047 | when "Dan", "Daniel" |
2646 | print "Your name, it's Dan" | 3048 | print "Your name, it's Dan" |
2647 | else | 3049 | else |
2648 | print "I don't know about your name" | 3050 | print "I don't know about you with name #{name}" |
2649 | </pre> | 3051 | </pre> |
2650 | </YueDisplay> | 3052 | </YueDisplay> |
2651 | 3053 | ||
@@ -2676,7 +3078,7 @@ next_number = switch b | |||
2676 | </pre> | 3078 | </pre> |
2677 | </YueDisplay> | 3079 | </YueDisplay> |
2678 | 3080 | ||
2679 | We can use the then keyword to write a switch’s when block on a single line. No extra keyword is needed to write the else block on a single line. | 3081 | We can use the then keyword to write a switch's when block on a single line. No extra keyword is needed to write the else block on a single line. |
2680 | 3082 | ||
2681 | ```moonscript | 3083 | ```moonscript |
2682 | msg = switch math.random(1, 5) | 3084 | msg = switch math.random(1, 5) |
@@ -2722,7 +3124,7 @@ else | |||
2722 | </pre> | 3124 | </pre> |
2723 | </YueDisplay> | 3125 | </YueDisplay> |
2724 | 3126 | ||
2725 | It is worth noting the order of the case comparison expression. The case’s expression is on the left hand side. This can be useful if the case’s expression wants to overwrite how the comparison is done by defining an eq metamethod. | 3127 | It is worth noting the order of the case comparison expression. The case's expression is on the left hand side. This can be useful if the case's expression wants to overwrite how the comparison is done by defining an eq metamethod. |
2726 | 3128 | ||
2727 | ### Table Matching | 3129 | ### Table Matching |
2728 | 3130 | ||
@@ -2782,6 +3184,123 @@ switch item | |||
2782 | </pre> | 3184 | </pre> |
2783 | </YueDisplay> | 3185 | </YueDisplay> |
2784 | 3186 | ||
3187 | You can also match against array elements, table fields, and even nested structures with array or table literals. | ||
3188 | |||
3189 | Match against array elements. | ||
3190 | |||
3191 | ```moonscript | ||
3192 | switch tb | ||
3193 | when [1, 2, 3] | ||
3194 | print "1, 2, 3" | ||
3195 | when [1, b, 3] | ||
3196 | print "1, #{b}, 3" | ||
3197 | when [1, 2, b = 3] -- b has a default value | ||
3198 | print "1, 2, #{b}" | ||
3199 | ``` | ||
3200 | <YueDisplay> | ||
3201 | <pre> | ||
3202 | switch tb | ||
3203 | when [1, 2, 3] | ||
3204 | print "1, 2, 3" | ||
3205 | when [1, b, 3] | ||
3206 | print "1, #{b}, 3" | ||
3207 | when [1, 2, b = 3] -- b has a default value | ||
3208 | print "1, 2, #{b}" | ||
3209 | </pre> | ||
3210 | </YueDisplay> | ||
3211 | |||
3212 | Match against table fields with destructuring. | ||
3213 | |||
3214 | ```moonscript | ||
3215 | switch tb | ||
3216 | when success: true, :result | ||
3217 | print "success", result | ||
3218 | when success: false | ||
3219 | print "failed", result | ||
3220 | else | ||
3221 | print "invalid" | ||
3222 | ``` | ||
3223 | <YueDisplay> | ||
3224 | <pre> | ||
3225 | switch tb | ||
3226 | when success: true, :result | ||
3227 | print "success", result | ||
3228 | when success: false | ||
3229 | print "failed", result | ||
3230 | else | ||
3231 | print "invalid" | ||
3232 | </pre> | ||
3233 | </YueDisplay> | ||
3234 | |||
3235 | Match against nested table structures. | ||
3236 | |||
3237 | ```moonscript | ||
3238 | switch tb | ||
3239 | when data: {type: "success", :content} | ||
3240 | print "success", content | ||
3241 | when data: {type: "error", :content} | ||
3242 | print "failed", content | ||
3243 | else | ||
3244 | print "invalid" | ||
3245 | ``` | ||
3246 | <YueDisplay> | ||
3247 | <pre> | ||
3248 | switch tb | ||
3249 | when data: {type: "success", :content} | ||
3250 | print "success", content | ||
3251 | when data: {type: "error", :content} | ||
3252 | print "failed", content | ||
3253 | else | ||
3254 | print "invalid" | ||
3255 | </pre> | ||
3256 | </YueDisplay> | ||
3257 | |||
3258 | Match against array of tables. | ||
3259 | |||
3260 | ```moonscript | ||
3261 | switch tb | ||
3262 | when [ | ||
3263 | {a: 1, b: 2} | ||
3264 | {a: 3, b: 4} | ||
3265 | {a: 5, b: 6} | ||
3266 | fourth | ||
3267 | ] | ||
3268 | print "matched", fourth | ||
3269 | ``` | ||
3270 | <YueDisplay> | ||
3271 | <pre> | ||
3272 | switch tb | ||
3273 | when [ | ||
3274 | {a: 1, b: 2} | ||
3275 | {a: 3, b: 4} | ||
3276 | {a: 5, b: 6} | ||
3277 | fourth | ||
3278 | ] | ||
3279 | print "matched", fourth | ||
3280 | </pre> | ||
3281 | </YueDisplay> | ||
3282 | |||
3283 | Match against a list and capture a range of elements. | ||
3284 | |||
3285 | ```moonscript | ||
3286 | segments = ["admin", "users", "logs", "view"] | ||
3287 | switch segments | ||
3288 | when [...groups, resource, action] | ||
3289 | print "Group:", groups -- prints: {"admin", "users"} | ||
3290 | print "Resource:", resource -- prints: "logs" | ||
3291 | print "Action:", action -- prints: "view" | ||
3292 | ``` | ||
3293 | <YueDisplay> | ||
3294 | <pre> | ||
3295 | segments = ["admin", "users", "logs", "view"] | ||
3296 | switch segments | ||
3297 | when [...groups, resource, action] | ||
3298 | print "Group:", groups -- prints: {"admin", "users"} | ||
3299 | print "Resource:", resource -- prints: "logs" | ||
3300 | print "Action:", action -- prints: "view" | ||
3301 | </pre> | ||
3302 | </YueDisplay> | ||
3303 | |||
2785 | ## Object Oriented Programming | 3304 | ## Object Oriented Programming |
2786 | 3305 | ||
2787 | In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the YueScript code at first, then look into the Lua code if you wish to know the implementation details. | 3306 | In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the YueScript code at first, then look into the Lua code if you wish to know the implementation details. |
@@ -2913,7 +3432,7 @@ class BackPack extends Inventory | |||
2913 | 3432 | ||
2914 | Here we extend our Inventory class, and limit the amount of items it can carry. | 3433 | Here we extend our Inventory class, and limit the amount of items it can carry. |
2915 | 3434 | ||
2916 | In this example, we don’t define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. | 3435 | In this example, we don't define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. |
2917 | 3436 | ||
2918 | Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. | 3437 | Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. |
2919 | 3438 | ||
@@ -3000,13 +3519,13 @@ print BackPack.size -- prints 10 | |||
3000 | 3519 | ||
3001 | The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. | 3520 | The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. |
3002 | 3521 | ||
3003 | The class object can be called like a function in order to create new instances. That’s how we created instances of classes in the examples above. | 3522 | The class object can be called like a function in order to create new instances. That's how we created instances of classes in the examples above. |
3004 | 3523 | ||
3005 | A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. | 3524 | A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. |
3006 | 3525 | ||
3007 | The class object’s metatable reads properties from the base if they don’t exist in the class object. This means we can access functions and properties directly from the class. | 3526 | The class object's metatable reads properties from the base if they don't exist in the class object. This means we can access functions and properties directly from the class. |
3008 | 3527 | ||
3009 | It is important to note that assigning to the class object does not assign into the base, so it’s not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. | 3528 | It is important to note that assigning to the class object does not assign into the base, so it's not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. |
3010 | 3529 | ||
3011 | The class object has a couple special properties: | 3530 | The class object has a couple special properties: |
3012 | 3531 | ||
@@ -3079,7 +3598,7 @@ print Counter.count -- prints 2 | |||
3079 | </pre> | 3598 | </pre> |
3080 | </YueDisplay> | 3599 | </YueDisplay> |
3081 | 3600 | ||
3082 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua’s colon syntax. | 3601 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax. |
3083 | 3602 | ||
3084 | ```moonscript | 3603 | ```moonscript |
3085 | @@hello 1,2,3,4 | 3604 | @@hello 1,2,3,4 |
@@ -3094,7 +3613,7 @@ The calling semantics of @@ are similar to @. Calling a @@ name will pass the cl | |||
3094 | 3613 | ||
3095 | In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. | 3614 | In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. |
3096 | 3615 | ||
3097 | Here is an alternative way to create a class variable compared to what’s described above: | 3616 | Here is an alternative way to create a class variable compared to what's described above: |
3098 | 3617 | ||
3099 | ```moonscript | 3618 | ```moonscript |
3100 | class Things | 3619 | class Things |
@@ -3360,19 +3879,19 @@ In this usage, with can be seen as a special form of the K combinator. | |||
3360 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. | 3879 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. |
3361 | 3880 | ||
3362 | ```moonscript | 3881 | ```moonscript |
3363 | with str = "Hello" | 3882 | with str := "Hello" |
3364 | print "original:", str | 3883 | print "original:", str |
3365 | print "upper:", \upper! | 3884 | print "upper:", \upper! |
3366 | ``` | 3885 | ``` |
3367 | <YueDisplay> | 3886 | <YueDisplay> |
3368 | <pre> | 3887 | <pre> |
3369 | with str = "Hello" | 3888 | with str := "Hello" |
3370 | print "original:", str | 3889 | print "original:", str |
3371 | print "upper:", \upper! | 3890 | print "upper:", \upper! |
3372 | </pre> | 3891 | </pre> |
3373 | </YueDisplay> | 3892 | </YueDisplay> |
3374 | 3893 | ||
3375 | Accessing special keys with `[]` in a `with` statement. | 3894 | You can access special keys with `[]` in a `with` statement. |
3376 | 3895 | ||
3377 | ```moonscript | 3896 | ```moonscript |
3378 | with tb | 3897 | with tb |
@@ -3395,6 +3914,18 @@ with tb | |||
3395 | </pre> | 3914 | </pre> |
3396 | </YueDisplay> | 3915 | </YueDisplay> |
3397 | 3916 | ||
3917 | `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. | ||
3918 | |||
3919 | ```moonscript | ||
3920 | with? obj | ||
3921 | print obj.name | ||
3922 | ``` | ||
3923 | <YueDisplay> | ||
3924 | <pre> | ||
3925 | with? obj | ||
3926 | print obj.name | ||
3927 | </pre> | ||
3928 | </YueDisplay> | ||
3398 | 3929 | ||
3399 | ## Do | 3930 | ## Do |
3400 | 3931 | ||
@@ -3415,7 +3946,7 @@ print var -- nil here | |||
3415 | </pre> | 3946 | </pre> |
3416 | </YueDisplay> | 3947 | </YueDisplay> |
3417 | 3948 | ||
3418 | YueScript’s **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. | 3949 | YueScript's **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. |
3419 | 3950 | ||
3420 | ```moonscript | 3951 | ```moonscript |
3421 | counter = do | 3952 | counter = do |
@@ -3541,7 +4072,7 @@ print i -- will print 0 | |||
3541 | </pre> | 4072 | </pre> |
3542 | </YueDisplay> | 4073 | </YueDisplay> |
3543 | 4074 | ||
3544 | In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn’t clear what names have already been declared. | 4075 | In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn't clear what names have already been declared. |
3545 | 4076 | ||
3546 | It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. | 4077 | It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. |
3547 | 4078 | ||
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md index 754566c..5cfe4e6 100755 --- a/doc/docs/zh/doc/README.md +++ b/doc/docs/zh/doc/README.md | |||
@@ -16,19 +16,29 @@ Yueï¼ˆæœˆï¼‰æ˜¯ä¸æ–‡ä¸â€œæœˆäº®â€çš„å称。 | |||
16 | ### 月之脚本概览 | 16 | ### 月之脚本概览 |
17 | ```moonscript | 17 | ```moonscript |
18 | -- å¯¼å…¥è¯æ³• | 18 | -- å¯¼å…¥è¯æ³• |
19 | import "yue" as :p, :to_lua | 19 | import p, to_lua from "yue" |
20 | 20 | ||
21 | -- éšå¼å¯¹è±¡ | 21 | -- éšå¼å¯¹è±¡ |
22 | inventory = | 22 | inventory = |
23 | equipment: | 23 | equipment: |
24 | * "sword" | 24 | - "sword" |
25 | * "shield" | 25 | - "shield" |
26 | items: | 26 | items: |
27 | * name: "potion" | 27 | - name: "potion" |
28 | count: 10 | 28 | count: 10 |
29 | * name: "bread" | 29 | - name: "bread" |
30 | count: 3 | 30 | count: 3 |
31 | 31 | ||
32 | -- 列表推导 | ||
33 | map = (arr, action) -> | ||
34 | [action item for item in *arr] | ||
35 | |||
36 | filter = (arr, cond) -> | ||
37 | [item for item in *arr when cond item] | ||
38 | |||
39 | reduce = (arr, init, action): init -> | ||
40 | init = action init, item for item in *arr | ||
41 | |||
32 | -- ç®¡é“æ“作符 | 42 | -- ç®¡é“æ“作符 |
33 | [1, 2, 3] | 43 | [1, 2, 3] |
34 | |> map (x) -> x * 2 | 44 | |> map (x) -> x * 2 |
@@ -51,19 +61,29 @@ export 🌛 = "月之脚本" | |||
51 | <YueDisplay> | 61 | <YueDisplay> |
52 | <pre> | 62 | <pre> |
53 | -- å¯¼å…¥è¯æ³• | 63 | -- å¯¼å…¥è¯æ³• |
54 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
55 | 65 | ||
56 | -- éšå¼å¯¹è±¡ | 66 | -- éšå¼å¯¹è±¡ |
57 | inventory = | 67 | inventory = |
58 | equipment: | 68 | equipment: |
59 | * "sword" | 69 | - "sword" |
60 | * "shield" | 70 | - "shield" |
61 | items: | 71 | items: |
62 | * name: "potion" | 72 | - name: "potion" |
63 | count: 10 | 73 | count: 10 |
64 | * name: "bread" | 74 | - name: "bread" |
65 | count: 3 | 75 | count: 3 |
66 | 76 | ||
77 | -- 列表推导 | ||
78 | map = (arr, action) -> | ||
79 | [action item for item in *arr] | ||
80 | |||
81 | filter = (arr, cond) -> | ||
82 | [item for item in *arr when cond item] | ||
83 | |||
84 | reduce = (arr, init, action): init -> | ||
85 | init = action init, item for item in *arr | ||
86 | |||
67 | -- ç®¡é“æ“作符 | 87 | -- ç®¡é“æ“作符 |
68 | [1, 2, 3] | 88 | [1, 2, 3] |
69 | |> map (x) -> x * 2 | 89 | |> map (x) -> x * 2 |
@@ -122,7 +142,7 @@ export 🌛 = "月之脚本" | |||
122 | 142 | ||
123 | * **下载预编译的二进制程åº** | 143 | * **下载预编译的二进制程åº** |
124 | 144 | ||
125 |  您å¯ä»¥ä¸‹è½½é¢„编译的二进制程åºï¼ŒåŒ…括兼容ä¸åŒ Lua ç‰ˆæœ¬çš„äºŒè¿›åˆ¶å¯æ‰§è¡Œæ–‡ä»¶å’Œåº“文件。 | 145 |  ä½ å¯ä»¥ä¸‹è½½é¢„编译的二进制程åºï¼ŒåŒ…括兼容ä¸åŒ Lua ç‰ˆæœ¬çš„äºŒè¿›åˆ¶å¯æ‰§è¡Œæ–‡ä»¶å’Œåº“文件。 |
126 | 146 | ||
127 |  在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程åºã€‚ | 147 |  在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程åºã€‚ |
128 | 148 | ||
@@ -132,14 +152,14 @@ export 🌛 = "月之脚本" | |||
132 | 152 | ||
133 | 在Luaä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬æ¨¡å—: | 153 | 在Luaä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬æ¨¡å—: |
134 | 154 | ||
135 | * **用法 1** | 155 | * **用法 1** |
136 | 在Luaä¸å¼•å…¥ "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue"。 | 156 | 在Luaä¸å¼•å…¥ "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue"。 |
137 | ```Lua | 157 | ```Lua |
138 | require("yue")("ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶") | 158 | require("yue")("ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶") |
139 | ``` | 159 | ``` |
140 | å½“ä½ åœ¨åŒä¸€è·¯å¾„下把 "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue" 编译æˆäº† "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.lua" 时,ä»ç„¶å¯ä»¥ä½¿ç”¨è¿™ä¸ªä»£ç åŠ è½½ .lua ä»£ç æ–‡ä»¶ã€‚在其余的月之脚本文件ä¸ï¼Œåªéœ€æ£å¸¸ä½¿ç”¨ **require** 或 **import**进行脚本引用å³å¯ã€‚错误消æ¯ä¸çš„代ç 行å·ä¹Ÿä¼šè¢«æ£ç¡®å¤„ç†ã€‚ | 160 | å½“ä½ åœ¨åŒä¸€è·¯å¾„下把 "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue" 编译æˆäº† "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.lua" 时,ä»ç„¶å¯ä»¥ä½¿ç”¨è¿™ä¸ªä»£ç åŠ è½½ .lua ä»£ç æ–‡ä»¶ã€‚在其余的月之脚本文件ä¸ï¼Œåªéœ€æ£å¸¸ä½¿ç”¨ **require** 或 **import**进行脚本引用å³å¯ã€‚错误消æ¯ä¸çš„代ç 行å·ä¹Ÿä¼šè¢«æ£ç¡®å¤„ç†ã€‚ |
141 | 161 | ||
142 | * **用法 2** | 162 | * **用法 2** |
143 | 手动引入月之脚本模å—å¹¶é‡å†™é”™è¯¯æ¶ˆæ¯æ¥å¸®åŠ©è°ƒè¯•ã€‚ | 163 | 手动引入月之脚本模å—å¹¶é‡å†™é”™è¯¯æ¶ˆæ¯æ¥å¸®åŠ©è°ƒè¯•ã€‚ |
144 | ```lua | 164 | ```lua |
145 | local yue = require("yue") | 165 | local yue = require("yue") |
@@ -151,7 +171,7 @@ end, function(err) | |||
151 | end) | 171 | end) |
152 | ``` | 172 | ``` |
153 | 173 | ||
154 | * **用法 3** | 174 | * **用法 3** |
155 | 在Luaä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬ç¼–è¯‘å™¨åŠŸèƒ½ã€‚ | 175 | 在Luaä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬ç¼–è¯‘å™¨åŠŸèƒ½ã€‚ |
156 | ```lua | 176 | ```lua |
157 | local yue = require("yue") | 177 | local yue = require("yue") |
@@ -202,12 +222,12 @@ f! | |||
202 | 䏿·»åŠ ä»»ä½•é€‰é¡¹æ‰§è¡Œå‘½ä»¤å¯ä»¥è¿›å…¥REPL模å¼ï¼Œ | 222 | 䏿·»åŠ ä»»ä½•é€‰é¡¹æ‰§è¡Œå‘½ä»¤å¯ä»¥è¿›å…¥REPL模å¼ï¼Œ |
203 | 在å•è¡Œè¾“å…¥ç¬¦å· '$' å¹¶æ¢è¡ŒåŽï¼Œå¯ä»¥å¼€å§‹æˆ–æ˜¯åœæ¢å¤šè¡Œè¾“å…¥æ¨¡å¼ | 223 | 在å•è¡Œè¾“å…¥ç¬¦å· '$' å¹¶æ¢è¡ŒåŽï¼Œå¯ä»¥å¼€å§‹æˆ–æ˜¯åœæ¢å¤šè¡Œè¾“å…¥æ¨¡å¼ |
204 | ``` | 224 | ``` |
205 |   使用案例: | 225 |   使用案例: |
206 |   递归编译当å‰è·¯å¾„下扩展å为 **.yue** çš„æ¯ä¸ªæœˆä¹‹è„šæœ¬æ–‡ä»¶ï¼š **yue .** | 226 |   递归编译当å‰è·¯å¾„下扩展å为 **.yue** çš„æ¯ä¸ªæœˆä¹‹è„šæœ¬æ–‡ä»¶ï¼š **yue .** |
207 |   编译并将结果ä¿å˜åˆ°ç›®æ ‡è·¯å¾„: **yue -t /target/path/ .** | 227 |   编译并将结果ä¿å˜åˆ°ç›®æ ‡è·¯å¾„: **yue -t /target/path/ .** |
208 |   编译并ä¿ç•™è°ƒè¯•ä¿¡æ¯ï¼š **yue -l .** | 228 |   编译并ä¿ç•™è°ƒè¯•ä¿¡æ¯ï¼š **yue -l .** |
209 |   编译并生æˆåŽ‹ç¼©ä»£ç : **yue -m .** | 229 |   编译并生æˆåŽ‹ç¼©ä»£ç : **yue -m .** |
210 |   直接执行代ç : **yue -e 'print 123'** | 230 |   直接执行代ç : **yue -e 'print 123'** |
211 |   执行一个月之脚本文件: **yue -e main.yue** | 231 |   执行一个月之脚本文件: **yue -e main.yue** |
212 | 232 | ||
213 | ## å® | 233 | ## å® |
@@ -333,7 +353,7 @@ end | |||
333 | 353 | ||
334 | ### å¯¼å‡ºå® | 354 | ### å¯¼å‡ºå® |
335 | 355 | ||
336 | å®å‡½æ•°å¯ä»¥ä»Žä¸€ä¸ªæ¨¡å—ä¸å¯¼å‡ºï¼Œå¹¶åœ¨å¦ä¸€ä¸ªæ¨¡å—ä¸å¯¼å…¥ã€‚您必须将导出的å®å‡½æ•°æ”¾åœ¨ä¸€ä¸ªå•独的文件ä¸ä½¿ç”¨ï¼Œè€Œä¸”åªæœ‰å®å®šä¹‰ã€å®å¯¼å…¥å’Œå®å±•å¼€å¯ä»¥æ”¾å…¥è¿™ä¸ªå®å¯¼å‡ºæ¨¡å—ä¸ã€‚ | 356 | å®å‡½æ•°å¯ä»¥ä»Žä¸€ä¸ªæ¨¡å—ä¸å¯¼å‡ºï¼Œå¹¶åœ¨å¦ä¸€ä¸ªæ¨¡å—ä¸å¯¼å…¥ã€‚ä½ å¿…é¡»å°†å¯¼å‡ºçš„å®å‡½æ•°æ”¾åœ¨ä¸€ä¸ªå•独的文件ä¸ä½¿ç”¨ï¼Œè€Œä¸”åªæœ‰å®å®šä¹‰ã€å®å¯¼å…¥å’Œå®å±•å¼€å¯ä»¥æ”¾å…¥è¿™ä¸ªå®å¯¼å‡ºæ¨¡å—ä¸ã€‚ |
337 | ```moonscript | 357 | ```moonscript |
338 | -- 文件: utils.yue | 358 | -- 文件: utils.yue |
339 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | 359 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" |
@@ -422,6 +442,54 @@ print "有效的枚举类型:", $BodyType Static | |||
422 | </pre> | 442 | </pre> |
423 | </YueDisplay> | 443 | </YueDisplay> |
424 | 444 | ||
445 | ### å®å‚数检查 | ||
446 | |||
447 | å¯ä»¥ç›´æŽ¥åœ¨å‚数列表ä¸å£°æ˜ŽæœŸæœ›çš„ AST èŠ‚ç‚¹ç±»åž‹ï¼Œå¹¶åœ¨ç¼–è¯‘æ—¶æ£€æŸ¥ä¼ å…¥çš„å®å‚数是å¦ç¬¦åˆé¢„期。 | ||
448 | |||
449 | ```moonscript | ||
450 | macro printNumAndStr = (num `Num, str `String) -> | | ||
451 | print( | ||
452 | #{num} | ||
453 | #{str} | ||
454 | ) | ||
455 | |||
456 | $printNumAndStr 123, "hello" | ||
457 | ``` | ||
458 | <YueDisplay> | ||
459 | <pre> | ||
460 | macro printNumAndStr = (num `Num, str `String) -> | | ||
461 | print( | ||
462 | #{num} | ||
463 | #{str} | ||
464 | ) | ||
465 | |||
466 | $printNumAndStr 123, "hello" | ||
467 | </pre> | ||
468 | </YueDisplay> | ||
469 | |||
470 | 如果需è¦åšæ›´åŠ çµæ´»çš„傿•°æ£€æŸ¥æ“作,å¯ä»¥ä½¿ç”¨å†…置的 `$is_ast` å®å‡½æ•°åœ¨åˆé€‚çš„ä½ç½®è¿›è¡Œæ‰‹åŠ¨æ£€æŸ¥ã€‚ | ||
471 | |||
472 | ```moonscript | ||
473 | macro printNumAndStr = (num, str) -> | ||
474 | error "expected Num as first argument" unless $is_ast Num, num | ||
475 | error "expected String as second argument" unless $is_ast String, str | ||
476 | "print(#{num}, #{str})" | ||
477 | |||
478 | $printNumAndStr 123, "hello" | ||
479 | ``` | ||
480 | <YueDisplay> | ||
481 | <pre> | ||
482 | macro printNumAndStr = (num, str) -> | ||
483 | error "expected Num as first argument" unless $is_ast Num, num | ||
484 | error "expected String as second argument" unless $is_ast String, str | ||
485 | "print(#{num}, #{str})" | ||
486 | |||
487 | $printNumAndStr 123, "hello" | ||
488 | </pre> | ||
489 | </YueDisplay> | ||
490 | |||
491 | 更多关于å¯ç”¨ AST 节点的详细信æ¯ï¼Œè¯·å‚考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) ä¸å¤§å†™çš„规则定义。 | ||
492 | |||
425 | ## æ“作符 | 493 | ## æ“作符 |
426 | 494 | ||
427 | Lua的所有二元和一元æ“作符在月之脚本ä¸éƒ½æ˜¯å¯ç”¨çš„。æ¤å¤–,**!=** ç¬¦å·æ˜¯ **~=** 的别å,而 **\\** 或 **::** å‡å¯ç”¨äºŽç¼–写链å¼å‡½æ•°è°ƒç”¨ï¼Œå¦‚写作 `tb\func!` 或 `tb::func!`。æ¤å¤–月之脚本还æä¾›äº†ä¸€äº›å…¶ä»–特殊的æ“作符,以编写更具表达力的代ç 。 | 495 | Lua的所有二元和一元æ“作符在月之脚本ä¸éƒ½æ˜¯å¯ç”¨çš„。æ¤å¤–,**!=** ç¬¦å·æ˜¯ **~=** 的别å,而 **\\** 或 **::** å‡å¯ç”¨äºŽç¼–写链å¼å‡½æ•°è°ƒç”¨ï¼Œå¦‚写作 `tb\func!` 或 `tb::func!`。æ¤å¤–月之脚本还æä¾›äº†ä¸€äº›å…¶ä»–特殊的æ“作符,以编写更具表达力的代ç 。 |
@@ -439,7 +507,7 @@ tb::func! if tb != nil | |||
439 | 507 | ||
440 | ### 链弿¯”较 | 508 | ### 链弿¯”较 |
441 | 509 | ||
442 | 您å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸è¿›è¡Œæ¯”较表达å¼çš„链å¼ä¹¦å†™ï¼š | 510 | ä½ å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸è¿›è¡Œæ¯”较表达å¼çš„链å¼ä¹¦å†™ï¼š |
443 | 511 | ||
444 | ```moonscript | 512 | ```moonscript |
445 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | 513 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 |
@@ -528,7 +596,7 @@ tab[] = "Value" | |||
528 | 596 | ||
529 | ### 表扩展 | 597 | ### 表扩展 |
530 | 598 | ||
531 | 您å¯ä»¥ä½¿ç”¨å‰ç½® `...` æ“作符在Luaè¡¨ä¸æ’入数组表或哈希表。 | 599 | ä½ å¯ä»¥ä½¿ç”¨å‰ç½® `...` æ“作符在Luaè¡¨ä¸æ’入数组表或哈希表。 |
532 | 600 | ||
533 | ```moonscript | 601 | ```moonscript |
534 | parts = | 602 | parts = |
@@ -565,11 +633,26 @@ merge = {...a, ...b} | |||
565 | </pre> | 633 | </pre> |
566 | </YueDisplay> | 634 | </YueDisplay> |
567 | 635 | ||
636 | ### 表åå‘索引 | ||
637 | |||
638 | ä½ å¯ä»¥ä½¿ç”¨ **#** æ“作符æ¥åå‘索引表ä¸çš„å…ƒç´ ã€‚ | ||
639 | |||
640 | ```moonscript | ||
641 | last = data.items[#] | ||
642 | second_last = data.items[#-1] | ||
643 | ``` | ||
644 | <YueDisplay> | ||
645 | <pre> | ||
646 | last = data.items[#] | ||
647 | second_last = data.items[#-1] | ||
648 | </pre> | ||
649 | </YueDisplay> | ||
650 | |||
568 | ### 元表 | 651 | ### 元表 |
569 | 652 | ||
570 | **<>** æ“ä½œç¬¦å¯æä¾›å…ƒè¡¨æ“ä½œçš„å¿«æ·æ–¹å¼ã€‚ | 653 | **<>** æ“ä½œç¬¦å¯æä¾›å…ƒè¡¨æ“ä½œçš„å¿«æ·æ–¹å¼ã€‚ |
571 | 654 | ||
572 | * **元表创建** | 655 | * **元表创建** |
573 | ä½¿ç”¨ç©ºæ‹¬å· **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。 | 656 | ä½¿ç”¨ç©ºæ‹¬å· **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。 |
574 | 657 | ||
575 | ```moonscript | 658 | ```moonscript |
@@ -605,7 +688,7 @@ close _ = <close>: -> print "超出范围" | |||
605 | </pre> | 688 | </pre> |
606 | </YueDisplay> | 689 | </YueDisplay> |
607 | 690 | ||
608 | * **元表访问** | 691 | * **元表访问** |
609 | 使用 **<>** 或被 **<>** åŒ…å›´çš„å…ƒæ–¹æ³•åæˆ–在 **<>** ä¸ç¼–写æŸäº›è¡¨è¾¾å¼æ¥è®¿é—®å…ƒè¡¨ã€‚ | 692 | 使用 **<>** 或被 **<>** åŒ…å›´çš„å…ƒæ–¹æ³•åæˆ–在 **<>** ä¸ç¼–写æŸäº›è¡¨è¾¾å¼æ¥è®¿é—®å…ƒè¡¨ã€‚ |
610 | 693 | ||
611 | ```moonscript | 694 | ```moonscript |
@@ -629,7 +712,7 @@ print tb.item | |||
629 | </pre> | 712 | </pre> |
630 | </YueDisplay> | 713 | </YueDisplay> |
631 | 714 | ||
632 | * **元表解构** | 715 | * **元表解构** |
633 | 使用被 **<>** 包围的元方法键解构元表。 | 716 | 使用被 **<>** 包围的元方法键解构元表。 |
634 | 717 | ||
635 | ```moonscript | 718 | ```moonscript |
@@ -680,7 +763,7 @@ with? io.open "test.txt", "w" | |||
680 | 763 | ||
681 | ### ç®¡é“ | 764 | ### ç®¡é“ |
682 | 765 | ||
683 | 与其使用一系列嵌套的函数调用,您还å¯ä»¥è€ƒè™‘使用è¿ç®—符 **|>** æ¥ä¼ 递值。 | 766 | ä¸Žå…¶ä½¿ç”¨ä¸€ç³»åˆ—åµŒå¥—çš„å‡½æ•°è°ƒç”¨ï¼Œä½ è¿˜å¯ä»¥è€ƒè™‘使用è¿ç®—符 **|>** æ¥ä¼ 递值。 |
684 | 767 | ||
685 | ```moonscript | 768 | ```moonscript |
686 | "ä½ å¥½" |> print | 769 | "ä½ å¥½" |> print |
@@ -731,67 +814,87 @@ a ??= false | |||
731 | 814 | ||
732 | ### éšå¼å¯¹è±¡ | 815 | ### éšå¼å¯¹è±¡ |
733 | 816 | ||
734 | 您å¯ä»¥åœ¨è¡¨æ ¼å—å†…ä½¿ç”¨ç¬¦å· **\*** 开始编写一系列éšå¼ç»“构。如果您æ£åœ¨åˆ›å»ºéšå¼å¯¹è±¡ï¼Œå¯¹è±¡çš„å—æ®µå¿…须具有相åŒçš„缩进。 | 817 | ä½ å¯ä»¥åœ¨è¡¨æ ¼å—å†…ä½¿ç”¨ç¬¦å· **\*** 或是 **-** 开始编写一系列éšå¼ç»“æž„ã€‚å¦‚æžœä½ æ£åœ¨åˆ›å»ºéšå¼å¯¹è±¡ï¼Œå¯¹è±¡çš„å—æ®µå¿…须具有相åŒçš„缩进。 |
818 | |||
735 | ```moonscript | 819 | ```moonscript |
820 | -- 赋值时使用éšå¼å¯¹è±¡ | ||
736 | list = | 821 | list = |
737 | * 1 | 822 | * 1 |
738 | * 2 | 823 | * 2 |
739 | * 3 | 824 | * 3 |
740 | 825 | ||
826 | -- 函数调用时使用éšå¼å¯¹è±¡ | ||
741 | func | 827 | func |
742 | * 1 | 828 | * 1 |
743 | * 2 | 829 | * 2 |
744 | * 3 | 830 | * 3 |
745 | 831 | ||
832 | -- 返回时使用éšå¼å¯¹è±¡ | ||
833 | f = -> | ||
834 | return | ||
835 | * 1 | ||
836 | * 2 | ||
837 | * 3 | ||
838 | |||
839 | -- è¡¨æ ¼æ—¶ä½¿ç”¨éšå¼å¯¹è±¡ | ||
746 | tb = | 840 | tb = |
747 | name: "abc" | 841 | name: "abc" |
748 | 842 | ||
749 | values: | 843 | values: |
750 | * "a" | 844 | - "a" |
751 | * "b" | 845 | - "b" |
752 | * "c" | 846 | - "c" |
753 | 847 | ||
754 | objects: | 848 | objects: |
755 | * name: "a" | 849 | - name: "a" |
756 | value: 1 | 850 | value: 1 |
757 | func: => @value + 1 | 851 | func: => @value + 1 |
758 | tb: | 852 | tb: |
759 | fieldA: 1 | 853 | fieldA: 1 |
760 | 854 | ||
761 | * name: "b" | 855 | - name: "b" |
762 | value: 2 | 856 | value: 2 |
763 | func: => @value + 2 | 857 | func: => @value + 2 |
764 | tb: { } | 858 | tb: { } |
765 | |||
766 | ``` | 859 | ``` |
767 | <YueDisplay> | 860 | <YueDisplay> |
768 | <pre> | 861 | <pre> |
862 | -- 赋值时使用éšå¼å¯¹è±¡ | ||
769 | list = | 863 | list = |
770 | * 1 | 864 | * 1 |
771 | * 2 | 865 | * 2 |
772 | * 3 | 866 | * 3 |
773 | 867 | ||
868 | -- 函数调用时使用éšå¼å¯¹è±¡ | ||
774 | func | 869 | func |
775 | * 1 | 870 | * 1 |
776 | * 2 | 871 | * 2 |
777 | * 3 | 872 | * 3 |
778 | 873 | ||
874 | -- 返回时使用éšå¼å¯¹è±¡ | ||
875 | f = -> | ||
876 | return | ||
877 | * 1 | ||
878 | * 2 | ||
879 | * 3 | ||
880 | |||
881 | -- è¡¨æ ¼æ—¶ä½¿ç”¨éšå¼å¯¹è±¡ | ||
779 | tb = | 882 | tb = |
780 | name: "abc" | 883 | name: "abc" |
781 | 884 | ||
782 | values: | 885 | values: |
783 | * "a" | 886 | - "a" |
784 | * "b" | 887 | - "b" |
785 | * "c" | 888 | - "c" |
786 | 889 | ||
787 | objects: | 890 | objects: |
788 | * name: "a" | 891 | - name: "a" |
789 | value: 1 | 892 | value: 1 |
790 | func: => @value + 1 | 893 | func: => @value + 1 |
791 | tb: | 894 | tb: |
792 | fieldA: 1 | 895 | fieldA: 1 |
793 | 896 | ||
794 | * name: "b" | 897 | - name: "b" |
795 | value: 2 | 898 | value: 2 |
796 | func: => @value + 2 | 899 | func: => @value + 2 |
797 | tb: { } | 900 | tb: { } |
@@ -859,7 +962,7 @@ do | |||
859 | 962 | ||
860 | 导出è¯å¥æä¾›äº†ä¸€ç§ç®€æ´çš„æ–¹å¼æ¥å®šä¹‰å½“å‰çš„æ¨¡å—。 | 963 | 导出è¯å¥æä¾›äº†ä¸€ç§ç®€æ´çš„æ–¹å¼æ¥å®šä¹‰å½“å‰çš„æ¨¡å—。 |
861 | 964 | ||
862 | * **命å导出** | 965 | * **命å导出** |
863 | 带命å的导出将定义一个局部å˜é‡ï¼Œå¹¶åœ¨å¯¼å‡ºçš„è¡¨ä¸æ·»åŠ ä¸€ä¸ªåŒåçš„å—æ®µã€‚ | 966 | 带命å的导出将定义一个局部å˜é‡ï¼Œå¹¶åœ¨å¯¼å‡ºçš„è¡¨ä¸æ·»åŠ ä¸€ä¸ªåŒåçš„å—æ®µã€‚ |
864 | 967 | ||
865 | ```moonscript | 968 | ```moonscript |
@@ -923,7 +1026,7 @@ export["a-b-c"] = 123 | |||
923 | </pre> | 1026 | </pre> |
924 | </YueDisplay> | 1027 | </YueDisplay> |
925 | 1028 | ||
926 | * **未命å导出** | 1029 | * **未命å导出** |
927 | 未命å导出会将è¦å¯¼å‡ºçš„ç›®æ ‡é¡¹ç›®æ·»åŠ åˆ°å¯¼å‡ºè¡¨çš„æ•°ç»„éƒ¨åˆ†ã€‚ | 1030 | 未命å导出会将è¦å¯¼å‡ºçš„ç›®æ ‡é¡¹ç›®æ·»åŠ åˆ°å¯¼å‡ºè¡¨çš„æ•°ç»„éƒ¨åˆ†ã€‚ |
928 | 1031 | ||
929 | ```moonscript | 1032 | ```moonscript |
@@ -953,7 +1056,7 @@ export with tmp | |||
953 | </pre> | 1056 | </pre> |
954 | </YueDisplay> | 1057 | </YueDisplay> |
955 | 1058 | ||
956 | * **默认导出** | 1059 | * **默认导出** |
957 | 在导出è¯å¥ä¸ä½¿ç”¨ **default** 关键å—ï¼Œæ¥æ›¿æ¢å¯¼å‡ºçš„è¡¨ä¸ºä¸€ä¸ªç›®æ ‡çš„å¯¹è±¡ã€‚ | 1060 | 在导出è¯å¥ä¸ä½¿ç”¨ **default** 关键å—ï¼Œæ¥æ›¿æ¢å¯¼å‡ºçš„è¡¨ä¸ºä¸€ä¸ªç›®æ ‡çš„å¯¹è±¡ã€‚ |
958 | 1061 | ||
959 | ```moonscript | 1062 | ```moonscript |
@@ -1223,7 +1326,7 @@ print first, second, color | |||
1223 | </pre> | 1326 | </pre> |
1224 | </YueDisplay> | 1327 | </YueDisplay> |
1225 | 1328 | ||
1226 | 在进行解构时,您å¯ä»¥æŒ‡å®šé»˜è®¤å€¼ï¼Œå¦‚: | 1329 | åœ¨è¿›è¡Œè§£æž„æ—¶ï¼Œä½ å¯ä»¥æŒ‡å®šé»˜è®¤å€¼ï¼Œå¦‚: |
1227 | 1330 | ||
1228 | ```moonscript | 1331 | ```moonscript |
1229 | {:name = "nameless", :job = "jobless"} = person | 1332 | {:name = "nameless", :job = "jobless"} = person |
@@ -1234,7 +1337,7 @@ print first, second, color | |||
1234 | </pre> | 1337 | </pre> |
1235 | </YueDisplay> | 1338 | </YueDisplay> |
1236 | 1339 | ||
1237 | 在进行列表解构时,您å¯ä»¥ä½¿ç”¨`_`作为å ä½ç¬¦ï¼š | 1340 | åœ¨è¿›è¡Œåˆ—è¡¨è§£æž„æ—¶ï¼Œä½ å¯ä»¥ä½¿ç”¨`_`作为å ä½ç¬¦ï¼š |
1238 | 1341 | ||
1239 | ```moonscript | 1342 | ```moonscript |
1240 | [_, two, _, four] = items | 1343 | [_, two, _, four] = items |
@@ -1245,9 +1348,55 @@ print first, second, color | |||
1245 | </pre> | 1348 | </pre> |
1246 | </YueDisplay> | 1349 | </YueDisplay> |
1247 | 1350 | ||
1248 | ### 在其它地方的解构 | 1351 | ### 范围解构 |
1352 | |||
1353 | ä½ å¯ä»¥ä½¿ç”¨å±•å¼€è¿ç®—符 `...` åœ¨åˆ—è¡¨è§£æž„ä¸æ¥æ•获一个范围的值到å列表ä¸ã€‚è¿™åœ¨å½“ä½ æƒ³è¦ä»Žåˆ—表的开头和结尾æå–ç‰¹å®šå…ƒç´ ï¼ŒåŒæ—¶æ”¶é›†ä¸é—´çš„å…ƒç´ æ—¶éžå¸¸æœ‰ç”¨ã€‚ | ||
1354 | |||
1355 | ```moonscript | ||
1356 | orders = ["first", "second", "third", "fourth", "last"] | ||
1357 | [first, ...bulk, last] = orders | ||
1358 | print first -- 打å°: first | ||
1359 | print bulk -- 打å°: {"second", "third", "fourth"} | ||
1360 | print last -- 打å°: last | ||
1361 | ``` | ||
1362 | <YueDisplay> | ||
1363 | <pre> | ||
1364 | orders = ["first", "second", "third", "fourth", "last"] | ||
1365 | [first, ...bulk, last] = orders | ||
1366 | print first -- 打å°: first | ||
1367 | print bulk -- 打å°: {"second", "third", "fourth"} | ||
1368 | print last -- 打å°: last | ||
1369 | </pre> | ||
1370 | </YueDisplay> | ||
1371 | |||
1372 | 展开è¿ç®—符å¯ä»¥ç”¨åœ¨ä¸åŒçš„ä½ç½®æ¥æ•获ä¸åŒçš„èŒƒå›´ï¼Œå¹¶ä¸”ä½ å¯ä»¥ä½¿ç”¨ `_` 作为å ä½ç¬¦æ¥è¡¨ç¤ºä½ 想跳过对应范围的æ•获: | ||
1373 | |||
1374 | ```moonscript | ||
1375 | -- æ•èŽ·ç¬¬ä¸€ä¸ªå…ƒç´ ä¹‹åŽçš„æ‰€æœ‰å…ƒç´ | ||
1376 | [first, ...rest] = orders | ||
1377 | |||
1378 | -- æ•获最åŽä¸€ä¸ªå…ƒç´ 之å‰çš„æ‰€æœ‰å…ƒç´ | ||
1379 | [...start, last] = orders | ||
1380 | |||
1381 | -- 跳过ä¸é—´çš„å…ƒç´ ï¼Œåªæ•获第一个和最åŽä¸€ä¸ªå…ƒç´ | ||
1382 | [first, ..._, last] = orders | ||
1383 | ``` | ||
1384 | <YueDisplay> | ||
1385 | <pre> | ||
1386 | -- æ•èŽ·ç¬¬ä¸€ä¸ªå…ƒç´ ä¹‹åŽçš„æ‰€æœ‰å…ƒç´ | ||
1387 | [first, ...rest] = orders | ||
1388 | |||
1389 | -- æ•获最åŽä¸€ä¸ªå…ƒç´ 之å‰çš„æ‰€æœ‰å…ƒç´ | ||
1390 | [...start, last] = orders | ||
1391 | |||
1392 | -- 跳过ä¸é—´çš„å…ƒç´ ï¼Œåªæ•获第一个和最åŽä¸€ä¸ªå…ƒç´ | ||
1393 | [first, ..._, last] = orders | ||
1394 | </pre> | ||
1395 | </YueDisplay> | ||
1396 | |||
1397 | ### 在其它地方的解构赋值 | ||
1249 | 1398 | ||
1250 | 解构也å¯ä»¥å‡ºçŽ°åœ¨å…¶å®ƒéšå¼è¿›è¡Œèµ‹å€¼çš„åœ°æ–¹ã€‚ä¸€ä¸ªä¾‹åæ˜¯ç”¨åœ¨for循环: | 1399 | 解构赋值也å¯ä»¥å‡ºçŽ°åœ¨å…¶å®ƒéšå¼è¿›è¡Œèµ‹å€¼çš„åœ°æ–¹ã€‚ä¸€ä¸ªä¾‹åæ˜¯ç”¨åœ¨for循环ä¸ï¼š |
1251 | 1400 | ||
1252 | ```moonscript | 1401 | ```moonscript |
1253 | tuples = [ | 1402 | tuples = [ |
@@ -1322,7 +1471,7 @@ print "好的" | |||
1322 | 1471 | ||
1323 | ### While 赋值 | 1472 | ### While 赋值 |
1324 | 1473 | ||
1325 | 您å¯ä»¥åœ¨ while 循环ä¸åŒæ ·ä½¿ç”¨èµ‹å€¼æ¥èŽ·å–循环æ¡ä»¶çš„值。 | 1474 | ä½ å¯ä»¥åœ¨ while 循环ä¸åŒæ ·ä½¿ç”¨èµ‹å€¼æ¥èŽ·å–循环æ¡ä»¶çš„值。 |
1326 | ```moonscript | 1475 | ```moonscript |
1327 | while byte := stream\read_one! | 1476 | while byte := stream\read_one! |
1328 | -- 对 byte åšä¸€äº›æ“作 | 1477 | -- 对 byte åšä¸€äº›æ“作 |
@@ -1338,7 +1487,7 @@ while byte := stream\read_one! | |||
1338 | 1487 | ||
1339 | ## å¯å˜å‚数赋值 | 1488 | ## å¯å˜å‚数赋值 |
1340 | 1489 | ||
1341 | 您å¯ä»¥å°†å‡½æ•°è¿”回的结果赋值给一个å¯å˜å‚æ•°ç¬¦å· `...`。然åŽä½¿ç”¨Lua的方å¼è®¿é—®å…¶å†…容。 | 1490 | ä½ å¯ä»¥å°†å‡½æ•°è¿”回的结果赋值给一个å¯å˜å‚æ•°ç¬¦å· `...`。然åŽä½¿ç”¨Lua的方å¼è®¿é—®å…¶å†…容。 |
1342 | ```moonscript | 1491 | ```moonscript |
1343 | list = [1, 2, 3, 4, 5] | 1492 | list = [1, 2, 3, 4, 5] |
1344 | fn = (ok) -> ok, table.unpack list | 1493 | fn = (ok) -> ok, table.unpack list |
@@ -1360,7 +1509,7 @@ print ok, count, first | |||
1360 | 1509 | ||
1361 | ## 空白 | 1510 | ## 空白 |
1362 | 1511 | ||
1363 | æœˆä¹‹è„šæœ¬æ˜¯ä¸€ä¸ªå¯¹ç©ºç™½æ•æ„Ÿçš„è¯è¨€ã€‚您必须在相åŒçš„缩进ä¸ä½¿ç”¨ç©ºæ ¼ **' '** 或制表符 **'\t'** æ¥ç¼–写一些代ç å—,如函数体ã€å€¼åˆ—表和一些控制å—。包å«ä¸åŒç©ºç™½çš„表达å¼å¯èƒ½æ„味ç€ä¸åŒçš„事情。制表符被视为4ä¸ªç©ºæ ¼ï¼Œä½†æœ€å¥½ä¸è¦æ··åˆä½¿ç”¨ç©ºæ ¼å’Œåˆ¶è¡¨ç¬¦ã€‚ | 1512 | æœˆä¹‹è„šæœ¬æ˜¯ä¸€ä¸ªå¯¹ç©ºç™½æ•æ„Ÿçš„è¯è¨€ã€‚ä½ å¿…é¡»åœ¨ç›¸åŒçš„缩进ä¸ä½¿ç”¨ç©ºæ ¼ **' '** 或制表符 **'\t'** æ¥ç¼–写一些代ç å—,如函数体ã€å€¼åˆ—表和一些控制å—。包å«ä¸åŒç©ºç™½çš„表达å¼å¯èƒ½æ„味ç€ä¸åŒçš„事情。制表符被视为4ä¸ªç©ºæ ¼ï¼Œä½†æœ€å¥½ä¸è¦æ··åˆä½¿ç”¨ç©ºæ ¼å’Œåˆ¶è¡¨ç¬¦ã€‚ |
1364 | 1513 | ||
1365 | ### 多行链å¼è°ƒç”¨ | 1514 | ### 多行链å¼è°ƒç”¨ |
1366 | 1515 | ||
@@ -1474,6 +1623,47 @@ catch err | |||
1474 | </pre> | 1623 | </pre> |
1475 | </YueDisplay> | 1624 | </YueDisplay> |
1476 | 1625 | ||
1626 | ### 错误处ç†ç®€åŒ– | ||
1627 | |||
1628 | `try?` 是 `try` çš„åŠŸèƒ½ç®€åŒ–è¯æ³•,它ä¸å†è¿”回 `try` è¯å¥çš„布尔状æ€ï¼Œå¹¶åœ¨æˆåŠŸæ—¶ç›´æŽ¥è¿”å›ž `try` 代ç å—的结果,失败时返回 `nil` 值而éžé”™è¯¯å¯¹è±¡ã€‚ | ||
1629 | |||
1630 | ```moonscript | ||
1631 | a, b, c = try? func! | ||
1632 | |||
1633 | -- 与空值åˆå¹¶è¿ç®—符一起使用 | ||
1634 | a = (try? func!) ?? "default" | ||
1635 | |||
1636 | -- ä½œä¸ºå‡½æ•°å‚æ•° | ||
1637 | f try? func! | ||
1638 | |||
1639 | -- 带 catch å—çš„ try! | ||
1640 | f try? | ||
1641 | print 123 | ||
1642 | func! | ||
1643 | catch e | ||
1644 | print e | ||
1645 | e | ||
1646 | ``` | ||
1647 | <YueDisplay> | ||
1648 | <pre> | ||
1649 | a, b, c = try? func! | ||
1650 | |||
1651 | -- 与空值åˆå¹¶è¿ç®—符一起使用 | ||
1652 | a = (try? func!) ?? "default" | ||
1653 | |||
1654 | -- ä½œä¸ºå‡½æ•°å‚æ•° | ||
1655 | f try? func! | ||
1656 | |||
1657 | -- 带 catch å—çš„ try! | ||
1658 | f try? | ||
1659 | print 123 | ||
1660 | func! | ||
1661 | catch e | ||
1662 | print e | ||
1663 | e | ||
1664 | </pre> | ||
1665 | </YueDisplay> | ||
1666 | |||
1477 | ## 属性 | 1667 | ## 属性 |
1478 | 1668 | ||
1479 | 月之脚本现在æä¾›äº†Lua 5.4新增的å«åšå±žæ€§çš„è¯æ³•支æŒã€‚在月之脚本编译到的Luaç›®æ ‡ç‰ˆæœ¬ä½ŽäºŽ5.4æ—¶ï¼Œä½ ä»ç„¶å¯ä»¥åŒæ—¶ä½¿ç”¨`const`å’Œ`close`çš„å±žæ€§å£°æ˜Žè¯æ³•ï¼Œå¹¶èŽ·å¾—å¸¸é‡æ£€æŸ¥å’Œä½œç”¨åŸŸå›žè°ƒçš„功能。 | 1669 | 月之脚本现在æä¾›äº†Lua 5.4新增的å«åšå±žæ€§çš„è¯æ³•支æŒã€‚在月之脚本编译到的Luaç›®æ ‡ç‰ˆæœ¬ä½ŽäºŽ5.4æ—¶ï¼Œä½ ä»ç„¶å¯ä»¥åŒæ—¶ä½¿ç”¨`const`å’Œ`close`çš„å±žæ€§å£°æ˜Žè¯æ³•ï¼Œå¹¶èŽ·å¾—å¸¸é‡æ£€æŸ¥å’Œä½œç”¨åŸŸå›žè°ƒçš„功能。 |
@@ -1502,6 +1692,19 @@ const {:a, :b, c, d} = tb | |||
1502 | </pre> | 1692 | </pre> |
1503 | </YueDisplay> | 1693 | </YueDisplay> |
1504 | 1694 | ||
1695 | ä½ ä¹Ÿå¯ä»¥å£°æ˜Žå…¨å±€å˜é‡ä¸ºå¸¸é‡ã€‚ | ||
1696 | |||
1697 | ```moonscript | ||
1698 | global const Constant = 123 | ||
1699 | -- Constant = 1 | ||
1700 | ``` | ||
1701 | <YueDisplay> | ||
1702 | <pre> | ||
1703 | global const Constant = 123 | ||
1704 | -- Constant = 1 | ||
1705 | </pre> | ||
1706 | </YueDisplay> | ||
1707 | |||
1505 | ## å—é¢é‡ | 1708 | ## å—é¢é‡ |
1506 | 1709 | ||
1507 | Luaä¸çš„æ‰€æœ‰åŸºæœ¬å—é¢é‡éƒ½å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸ä½¿ç”¨ã€‚包括数å—ã€å—符串ã€å¸ƒå°”值和**nil**。 | 1710 | Luaä¸çš„æ‰€æœ‰åŸºæœ¬å—é¢é‡éƒ½å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸ä½¿ç”¨ã€‚包括数å—ã€å—符串ã€å¸ƒå°”值和**nil**。 |
@@ -1529,17 +1732,78 @@ print "我有#{math.random! * 100}%的把æ¡ã€‚" | |||
1529 | 1732 | ||
1530 | ### æ•°å—å—é¢é‡ | 1733 | ### æ•°å—å—é¢é‡ |
1531 | 1734 | ||
1532 | 您å¯ä»¥åœ¨æ•°å—å—é¢é‡ä¸ä½¿ç”¨ä¸‹åˆ’线æ¥å¢žåŠ å¯è¯»æ€§ã€‚ | 1735 | ä½ å¯ä»¥åœ¨æ•°å—å—é¢é‡ä¸ä½¿ç”¨ä¸‹åˆ’线æ¥å¢žåŠ å¯è¯»æ€§ã€‚ |
1533 | 1736 | ||
1534 | ```moonscript | 1737 | ```moonscript |
1535 | integer = 1_000_000 | 1738 | integer = 1_000_000 |
1536 | hex = 0xEF_BB_BF | 1739 | hex = 0xEF_BB_BF |
1740 | binary = 0B10011 | ||
1537 | ``` | 1741 | ``` |
1538 | <YueDisplay> | 1742 | <YueDisplay> |
1539 | 1743 | ||
1540 | <pre> | 1744 | <pre> |
1541 | integer = 1_000_000 | 1745 | integer = 1_000_000 |
1542 | hex = 0xEF_BB_BF | 1746 | hex = 0xEF_BB_BF |
1747 | binary = 0B10011 | ||
1748 | </pre> | ||
1749 | </YueDisplay> | ||
1750 | |||
1751 | ### YAML é£Žæ ¼å—符串 | ||
1752 | |||
1753 | 使用 `|` å‰ç¼€æ ‡è®°ä¸€ä¸ªå¤šè¡Œ YAML é£Žæ ¼å—符串: | ||
1754 | |||
1755 | ```moonscript | ||
1756 | str = | | ||
1757 | key: value | ||
1758 | list: | ||
1759 | - item1 | ||
1760 | - #{expr} | ||
1761 | ``` | ||
1762 | <YueDisplay> | ||
1763 | <pre> | ||
1764 | str = | | ||
1765 | key: value | ||
1766 | list: | ||
1767 | - item1 | ||
1768 | - #{expr} | ||
1769 | </pre> | ||
1770 | </YueDisplay> | ||
1771 | |||
1772 | 其效果类似于原生 Lua çš„å¤šè¡Œæ‹¼æŽ¥ï¼Œæ‰€æœ‰æ–‡æœ¬ï¼ˆå«æ¢è¡Œï¼‰å°†è¢«ä¿ç•™ä¸‹æ¥ï¼Œå¹¶æ”¯æŒ `#{...}` è¯æ³•,通过 `tostring(expr)` æ’入表达å¼ç»“果。 | ||
1773 | |||
1774 | YAML é£Žæ ¼çš„å¤šè¡Œå—ç¬¦ä¸²ä¼šè‡ªåŠ¨æ£€æµ‹é¦–è¡ŒåŽæœ€å°çš„公共缩进,并从所有行ä¸åˆ 除该å‰ç¼€ç©ºç™½å—ç¬¦ã€‚è¿™è®©ä½ å¯ä»¥åœ¨ä»£ç ä¸å¯¹é½æ–‡æœ¬ï¼Œä½†è¾“出å—符串ä¸ä¼šå¸¦å¤šä½™ç¼©è¿›ã€‚ | ||
1775 | |||
1776 | ```moonscript | ||
1777 | fn = -> | ||
1778 | str = | | ||
1779 | foo: | ||
1780 | bar: baz | ||
1781 | return str | ||
1782 | ``` | ||
1783 | <YueDisplay> | ||
1784 | <pre> | ||
1785 | fn = -> | ||
1786 | str = | | ||
1787 | foo: | ||
1788 | bar: baz | ||
1789 | return str | ||
1790 | </pre> | ||
1791 | </YueDisplay> | ||
1792 | |||
1793 | 输出å—符串ä¸çš„ foo: 对é½åˆ°è¡Œé¦–,ä¸ä¼šå¸¦æœ‰å‡½æ•°ç¼©è¿›ç©ºæ ¼ã€‚ä¿ç•™å†…部缩进的相对结构,适åˆä¹¦å†™ç»“æž„åŒ–åµŒå¥—æ ·å¼çš„内容。 | ||
1794 | |||
1795 | 支æŒè‡ªåЍ处ç†å—符ä¸çš„引å·ã€åæ–œæ ç‰ç‰¹æ®Šç¬¦å·ï¼Œæ— 需手动转义: | ||
1796 | |||
1797 | ```moonscript | ||
1798 | str = | | ||
1799 | path: "C:\Program Files\App" | ||
1800 | note: 'He said: "#{Hello}!"' | ||
1801 | ``` | ||
1802 | <YueDisplay> | ||
1803 | <pre> | ||
1804 | str = | | ||
1805 | path: "C:\Program Files\App" | ||
1806 | note: 'He said: "#{Hello}!"' | ||
1543 | </pre> | 1807 | </pre> |
1544 | </YueDisplay> | 1808 | </YueDisplay> |
1545 | 1809 | ||
@@ -1644,7 +1908,7 @@ print "æ•°å—的和是", sum 10, 20 | |||
1644 | </pre> | 1908 | </pre> |
1645 | </YueDisplay> | 1909 | </YueDisplay> |
1646 | 1910 | ||
1647 | 如果您需è¦åšæ˜¾å¼è¿”回,å¯ä»¥ä½¿ç”¨return关键å—: | 1911 | å¦‚æžœä½ éœ€è¦åšæ˜¾å¼è¿”回,å¯ä»¥ä½¿ç”¨return关键å—: |
1648 | 1912 | ||
1649 | ```moonscript | 1913 | ```moonscript |
1650 | sum = (x, y) -> return x + y | 1914 | sum = (x, y) -> return x + y |
@@ -1822,6 +2086,89 @@ if func 1, 2, 3, | |||
1822 | </pre> | 2086 | </pre> |
1823 | </YueDisplay> | 2087 | </YueDisplay> |
1824 | 2088 | ||
2089 | ### 傿•°è§£æž„ | ||
2090 | |||
2091 | 月之脚本支æŒåœ¨å‡½æ•°å½¢å‚ä½ç½®å¯¹ä¼ 入对象进行解构。适用两类解构表åé¢é‡ï¼š | ||
2092 | |||
2093 | - 使用 {} 包裹的å—é¢é‡/对象形å‚ï¼Œæ”¯æŒæä¾›èŽ·å¾—ç©ºå—æ®µæ—¶çš„默认值(例如 {:a, :b}ã€{a: a1 = 123})。 | ||
2094 | |||
2095 | - æ— {} 包裹ã€ä»¥é”®å€¼/简写键åºåˆ—开头,直至é‡åˆ°å…¶å®ƒè¡¨è¾¾å¼ç»ˆæ¢ï¼ˆä¾‹å¦‚ :a, b: b1, :c),表示从åŒä¸€ä¸ªå¯¹è±¡ä¸è§£æž„å¤šä¸ªå—æ®µã€‚ | ||
2096 | |||
2097 | ```moonscript | ||
2098 | f1 = (:a, :b, :c) -> | ||
2099 | print a, b, c | ||
2100 | |||
2101 | f1 a: 1, b: "2", c: {} | ||
2102 | |||
2103 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
2104 | print a1, b, c | ||
2105 | |||
2106 | arg1 = {a: 0} | ||
2107 | f2 arg1, arg2 | ||
2108 | ``` | ||
2109 | <YueDisplay> | ||
2110 | <pre> | ||
2111 | f1 = (:a, :b, :c) -> | ||
2112 | print a, b, c | ||
2113 | |||
2114 | f1 a: 1, b: "2", c: {} | ||
2115 | |||
2116 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
2117 | print a1, b, c | ||
2118 | |||
2119 | arg1 = {a: 0} | ||
2120 | f2 arg1, arg2 | ||
2121 | </pre> | ||
2122 | </YueDisplay> | ||
2123 | |||
2124 | ### å‰ç½®è¿”å›žè¡¨è¾¾å¼ | ||
2125 | |||
2126 | 在深度嵌套的函数体ä¸ï¼Œä¸ºäº†æå‡è¿”回值的å¯è¯»æ€§åŠç¼–写便利性,我们新增了 “å‰ç½®è¿”回表达å¼â€ è¯æ³•。其形å¼å¦‚下: | ||
2127 | |||
2128 | ```moon | ||
2129 | findFirstEven = (list): nil -> | ||
2130 | for item in *list | ||
2131 | if type(item) == "table" | ||
2132 | for sub in *item | ||
2133 | if sub % 2 == 0 | ||
2134 | return sub | ||
2135 | ``` | ||
2136 | <YueDisplay> | ||
2137 | <pre> | ||
2138 | findFirstEven = (list): nil -> | ||
2139 | for item in *list | ||
2140 | if type(item) == "table" | ||
2141 | for sub in *item | ||
2142 | if sub % 2 == 0 | ||
2143 | return sub | ||
2144 | </pre> | ||
2145 | </YueDisplay> | ||
2146 | |||
2147 | 这个写法ç‰ä»·äºŽï¼š | ||
2148 | |||
2149 | ```moon | ||
2150 | findFirstEven = (list) -> | ||
2151 | for item in *list | ||
2152 | if type(item) == "table" | ||
2153 | for sub in *item | ||
2154 | if sub % 2 == 0 | ||
2155 | return sub | ||
2156 | nil | ||
2157 | ``` | ||
2158 | <YueDisplay> | ||
2159 | <pre> | ||
2160 | findFirstEven = (list) -> | ||
2161 | for item in *list | ||
2162 | if type(item) == "table" | ||
2163 | for sub in *item | ||
2164 | if sub % 2 == 0 | ||
2165 | return sub | ||
2166 | nil | ||
2167 | </pre> | ||
2168 | </YueDisplay> | ||
2169 | |||
2170 | å”¯ä¸€çš„åŒºåˆ«åœ¨äºŽï¼šä½ å¯ä»¥å°†å‡½æ•°çš„è¿”å›žå€¼è¡¨è¾¾å¼æå‰å†™åœ¨ `->` 或 `=>` å‰ï¼Œç”¨ä»¥æŒ‡ç¤ºè¯¥å‡½æ•°åº”éšå¼è¿”回该表达å¼çš„å€¼ã€‚è¿™æ ·å³ä½¿åœ¨å¤šå±‚循环或æ¡ä»¶åˆ¤æ–çš„åœºæ™¯ä¸‹ï¼Œä¹Ÿæ— éœ€ç¼–å†™å°¾è¡Œæ‚¬æŒ‚çš„è¿”å›žè¡¨è¾¾å¼ï¼Œé€»è¾‘ç»“æž„ä¼šæ›´åŠ ç›´è§‚æ¸…æ™°ã€‚ | ||
2171 | |||
1825 | ## åå‘回调 | 2172 | ## åå‘回调 |
1826 | 2173 | ||
1827 | åå‘回调用于å‡å°‘函数回调的嵌套。它们使用指å‘左侧的ç®å¤´ï¼Œå¹¶ä¸”é»˜è®¤ä¼šè¢«å®šä¹‰ä¸ºä¼ å…¥åŽç»å‡½æ•°è°ƒç”¨çš„æœ€åŽä¸€ä¸ªå‚æ•°ã€‚å®ƒçš„è¯æ³•大部分与常规ç®å¤´å‡½æ•°ç›¸åŒï¼Œåªæ˜¯å®ƒæŒ‡å‘å¦ä¸€æ–¹å‘,并且åŽç»çš„函数体ä¸éœ€è¦è¿›è¡Œç¼©è¿›ã€‚ | 2174 | åå‘回调用于å‡å°‘函数回调的嵌套。它们使用指å‘左侧的ç®å¤´ï¼Œå¹¶ä¸”é»˜è®¤ä¼šè¢«å®šä¹‰ä¸ºä¼ å…¥åŽç»å‡½æ•°è°ƒç”¨çš„æœ€åŽä¸€ä¸ªå‚æ•°ã€‚å®ƒçš„è¯æ³•大部分与常规ç®å¤´å‡½æ•°ç›¸åŒï¼Œåªæ˜¯å®ƒæŒ‡å‘å¦ä¸€æ–¹å‘,并且åŽç»çš„函数体ä¸éœ€è¦è¿›è¡Œç¼©è¿›ã€‚ |
@@ -1850,7 +2197,7 @@ print @value | |||
1850 | </pre> | 2197 | </pre> |
1851 | </YueDisplay> | 2198 | </YueDisplay> |
1852 | 2199 | ||
1853 | 您å¯ä»¥é€šè¿‡ä¸€ä¸ªå ä½ç¬¦æŒ‡å®šå›žè°ƒå‡½æ•°çš„ä¼ å‚ä½ç½®ã€‚ | 2200 | ä½ å¯ä»¥é€šè¿‡ä¸€ä¸ªå ä½ç¬¦æŒ‡å®šå›žè°ƒå‡½æ•°çš„ä¼ å‚ä½ç½®ã€‚ |
1854 | 2201 | ||
1855 | ```moonscript | 2202 | ```moonscript |
1856 | (x) <- map _, [1, 2, 3] | 2203 | (x) <- map _, [1, 2, 3] |
@@ -1863,22 +2210,22 @@ x * 2 | |||
1863 | </pre> | 2210 | </pre> |
1864 | </YueDisplay> | 2211 | </YueDisplay> |
1865 | 2212 | ||
1866 | 如果您希望在åå‘回调处ç†åŽç»§ç»ç¼–写更多其它的代ç ,您å¯ä»¥ä½¿ç”¨doè¯å¥å°†ä¸å½’属åå‘回调的代ç 分开。 | 2213 | å¦‚æžœä½ å¸Œæœ›åœ¨åå‘回调处ç†åŽç»§ç»ç¼–写更多其它的代ç ,å¯ä»¥ä½¿ç”¨ do è¯å¥å°†ä¸å±žäºŽåå‘回调的代ç 分隔开。对于éžç²—ç®å¤´å‡½æ•°çš„åå‘回调,回调返回值的括å·ä¹Ÿæ˜¯å¯ä»¥çœç•¥çš„。 |
1867 | 2214 | ||
1868 | ```moonscript | 2215 | ```moonscript |
1869 | result, msg = do | 2216 | result, msg = do |
1870 | (data) <- readAsync "文件å.txt" | 2217 | data <- readAsync "文件å.txt" |
1871 | print data | 2218 | print data |
1872 | (info) <- processAsync data | 2219 | info <- processAsync data |
1873 | check info | 2220 | check info |
1874 | print result, msg | 2221 | print result, msg |
1875 | ``` | 2222 | ``` |
1876 | <YueDisplay> | 2223 | <YueDisplay> |
1877 | <pre> | 2224 | <pre> |
1878 | result, msg = do | 2225 | result, msg = do |
1879 | (data) <- readAsync "文件å.txt" | 2226 | data <- readAsync "文件å.txt" |
1880 | print data | 2227 | print data |
1881 | (info) <- processAsync data | 2228 | info <- processAsync data |
1882 | check info | 2229 | check info |
1883 | print result, msg | 2230 | print result, msg |
1884 | </pre> | 2231 | </pre> |
@@ -2037,7 +2384,7 @@ list_with_one_element = [ 1, ] | |||
2037 | 2384 | ||
2038 | ## æŽ¨å¯¼å¼ | 2385 | ## æŽ¨å¯¼å¼ |
2039 | 2386 | ||
2040 | 推导å¼ä¸ºæˆ‘们æä¾›äº†ä¸€ç§ä¾¿æ·çš„è¯æ³•,通过éåŽ†çŽ°æœ‰å¯¹è±¡å¹¶å¯¹å…¶å€¼åº”ç”¨è¡¨è¾¾å¼æ¥æž„é€ å‡ºæ–°çš„è¡¨æ ¼ã€‚æœˆä¹‹è„šæœ¬æœ‰ä¸¤ç§æŽ¨å¯¼å¼ï¼šåˆ—表推导å¼å’Œè¡¨æ ¼æŽ¨å¯¼å¼ã€‚它们最终都是产生Luaè¡¨æ ¼ï¼›åˆ—è¡¨æŽ¨å¯¼å¼å°†å€¼ç´¯ç§¯åˆ°ç±»ä¼¼æ•°ç»„çš„è¡¨æ ¼ä¸ï¼Œè€Œè¡¨æ ¼æŽ¨å¯¼å¼å…è®¸æ‚¨åœ¨æ¯æ¬¡éåŽ†æ—¶è®¾ç½®æ–°è¡¨æ ¼çš„é”®å’Œå€¼ã€‚ | 2387 | 推导å¼ä¸ºæˆ‘们æä¾›äº†ä¸€ç§ä¾¿æ·çš„è¯æ³•,通过éåŽ†çŽ°æœ‰å¯¹è±¡å¹¶å¯¹å…¶å€¼åº”ç”¨è¡¨è¾¾å¼æ¥æž„é€ å‡ºæ–°çš„è¡¨æ ¼ã€‚æœˆä¹‹è„šæœ¬æœ‰ä¸¤ç§æŽ¨å¯¼å¼ï¼šåˆ—表推导å¼å’Œè¡¨æ ¼æŽ¨å¯¼å¼ã€‚它们最终都是产生Luaè¡¨æ ¼ï¼›åˆ—è¡¨æŽ¨å¯¼å¼å°†å€¼ç´¯ç§¯åˆ°ç±»ä¼¼æ•°ç»„çš„è¡¨æ ¼ä¸ï¼Œè€Œè¡¨æ ¼æŽ¨å¯¼å¼å…è®¸ä½ åœ¨æ¯æ¬¡éåŽ†æ—¶è®¾ç½®æ–°è¡¨æ ¼çš„é”®å’Œå€¼ã€‚ |
2041 | 2388 | ||
2042 | ### åˆ—è¡¨æŽ¨å¯¼å¼ | 2389 | ### åˆ—è¡¨æŽ¨å¯¼å¼ |
2043 | 2390 | ||
@@ -2210,6 +2557,45 @@ slice = [item for item in *items[,,2]] | |||
2210 | </pre> | 2557 | </pre> |
2211 | </YueDisplay> | 2558 | </YueDisplay> |
2212 | 2559 | ||
2560 | 最å°å’Œæœ€å¤§è¾¹ç•Œéƒ½å¯ä»¥æ˜¯è´Ÿæ•°ï¼Œä½¿ç”¨è´Ÿæ•°æ„味ç€è¾¹ç•Œæ˜¯ä»Žè¡¨çš„æœ«å°¾å¼€å§‹è®¡ç®—的。 | ||
2561 | |||
2562 | ```moonscript | ||
2563 | -- å–æœ€åŽ4ä¸ªå…ƒç´ | ||
2564 | slice = [item for item in *items[-4,-1]] | ||
2565 | ``` | ||
2566 | <YueDisplay> | ||
2567 | <pre> | ||
2568 | -- å–æœ€åŽ4ä¸ªå…ƒç´ | ||
2569 | slice = [item for item in *items[-4,-1]] | ||
2570 | </pre> | ||
2571 | </YueDisplay> | ||
2572 | |||
2573 | 切片的æ¥é•¿ä¹Ÿå¯ä»¥æ˜¯è´Ÿæ•°ï¼Œè¿™æ„味ç€å…ƒç´ 会以相å的顺åºè¢«å–出。 | ||
2574 | |||
2575 | ```moonscript | ||
2576 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2577 | ``` | ||
2578 | <YueDisplay> | ||
2579 | <pre> | ||
2580 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2581 | </pre> | ||
2582 | </YueDisplay> | ||
2583 | |||
2584 | #### åˆ‡ç‰‡è¡¨è¾¾å¼ | ||
2585 | |||
2586 | 切片也å¯ä»¥ä½œä¸ºè¡¨è¾¾å¼æ¥ä½¿ç”¨ã€‚å¯ä»¥ç”¨äºŽèŽ·å–一个表包å«çš„å列表。 | ||
2587 | |||
2588 | ```moonscript | ||
2589 | -- å–第2和第4ä¸ªå…ƒç´ ä½œä¸ºæ–°çš„åˆ—è¡¨ | ||
2590 | sub_list = items[2, 4] | ||
2591 | ``` | ||
2592 | <YueDisplay> | ||
2593 | <pre> | ||
2594 | -- å–第2和第4ä¸ªå…ƒç´ ä½œä¸ºæ–°çš„åˆ—è¡¨ | ||
2595 | sub_list = items[2, 4] | ||
2596 | </pre> | ||
2597 | </YueDisplay> | ||
2598 | |||
2213 | ## for 循环 | 2599 | ## for 循环 |
2214 | 2600 | ||
2215 | Lua䏿œ‰ä¸¤ç§for循环形å¼ï¼Œæ•°å—型和通用型: | 2601 | Lua䏿œ‰ä¸¤ç§for循环形å¼ï¼Œæ•°å—型和通用型: |
@@ -2286,9 +2672,24 @@ doubled_evens = for i = 1, 20 | |||
2286 | </pre> | 2672 | </pre> |
2287 | </YueDisplay> | 2673 | </YueDisplay> |
2288 | 2674 | ||
2289 | 您还å¯ä»¥ç»“åˆfor循环表达å¼ä¸Žcontinueè¯å¥æ¥è¿‡æ»¤å€¼ã€‚ | 2675 | æ¤å¤–,for循环还支æŒå¸¦è¿”回值的breakè¯å¥ï¼Œè¿™æ ·å¾ªçŽ¯æœ¬èº«å°±å¯ä»¥ä½œä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œåœ¨æ»¡è¶³æ¡ä»¶æ—¶æå‰é€€å‡ºå¹¶è¿”回有æ„义的结果。 |
2676 | |||
2677 | 例如,查找第一个大于10的数å—: | ||
2678 | |||
2679 | ```moonscript | ||
2680 | first_large = for n in *numbers | ||
2681 | break n if n > 10 | ||
2682 | ``` | ||
2683 | <YueDisplay> | ||
2684 | <pre> | ||
2685 | first_large = for n in *numbers | ||
2686 | break n if n > 10 | ||
2687 | </pre> | ||
2688 | </YueDisplay> | ||
2689 | |||
2690 | ä½ è¿˜å¯ä»¥ç»“åˆfor循环表达å¼ä¸Žcontinueè¯å¥æ¥è¿‡æ»¤å€¼ã€‚ | ||
2290 | 2691 | ||
2291 | 注æ„出现在函数体末尾的for循环,ä¸ä¼šè¢«å½“作是一个表达å¼ï¼Œå¹¶å°†å¾ªçŽ¯ç»“æžœç´¯ç§¯åˆ°ä¸€ä¸ªåˆ—è¡¨ä¸ä½œä¸ºè¿”回值(相å,函数将返回nil)。如果è¦å‡½æ•°æœ«å°¾çš„循环转æ¢ä¸ºåˆ—表表达å¼ï¼Œå¯ä»¥ä½¿ç”¨è¿”回è¯å¥åŠ for循环表达å¼ã€‚ | 2692 | 注æ„出现在函数体末尾的for循环,ä¸ä¼šè¢«å½“作是一个表达å¼å¹¶å°†å¾ªçŽ¯ç»“æžœç´¯ç§¯åˆ°ä¸€ä¸ªåˆ—è¡¨ä¸ä½œä¸ºè¿”回值(相å,函数将返回nil)。如果è¦å‡½æ•°æœ«å°¾çš„循环转æ¢ä¸ºåˆ—表表达å¼ï¼Œå¯ä»¥æ˜¾å¼åœ°ä½¿ç”¨è¿”回è¯å¥åŠ for循环表达å¼ã€‚ |
2292 | 2693 | ||
2293 | ```moonscript | 2694 | ```moonscript |
2294 | func_a = -> for i = 1, 10 do print i | 2695 | func_a = -> for i = 1, 10 do print i |
@@ -2513,7 +2914,7 @@ print "ä½ çœŸå¹¸è¿ï¼" unless math.random! > 0.1 | |||
2513 | 2914 | ||
2514 | ### èŒƒå›´è¡¨è¾¾å¼ | 2915 | ### èŒƒå›´è¡¨è¾¾å¼ |
2515 | 2916 | ||
2516 | 您å¯ä»¥ä½¿ç”¨èŒƒå›´è¡¨è¾¾å¼æ¥ç¼–写进行范围检查的代ç 。 | 2917 | ä½ å¯ä»¥ä½¿ç”¨èŒƒå›´è¡¨è¾¾å¼æ¥ç¼–写进行范围检查的代ç 。 |
2517 | 2918 | ||
2518 | ```moonscript | 2919 | ```moonscript |
2519 | a = 5 | 2920 | a = 5 |
@@ -2586,28 +2987,26 @@ reader\parse_line! until reader\eof! | |||
2586 | 2987 | ||
2587 | ## switch è¯å¥ | 2988 | ## switch è¯å¥ |
2588 | 2989 | ||
2589 | switchè¯å¥æ˜¯ä¸ºäº†ç®€åŒ–检查一系列相åŒå€¼çš„ifè¯å¥è€Œæä¾›çš„ç®€å†™è¯æ³•ã€‚è¦æ³¨æ„ç”¨äºŽæ¯”è¾ƒæ£€æŸ¥çš„ç›®æ ‡å€¼åªä¼šè®¡ç®—一次。和ifè¯å¥ä¸€æ ·ï¼Œswitchè¯å¥åœ¨æœ€åŽå¯ä»¥æŽ¥ä¸€ä¸ªelse代ç å—æ¥å¤„ç†æ²¡æœ‰åŒ¹é…的情况。在生æˆçš„Lua代ç ä¸ï¼Œè¿›è¡Œæ¯”较是使用==æ“作符完æˆçš„。 | 2990 | switchè¯å¥æ˜¯ä¸ºäº†ç®€åŒ–检查一系列相åŒå€¼çš„ifè¯å¥è€Œæä¾›çš„ç®€å†™è¯æ³•ã€‚è¦æ³¨æ„ç”¨äºŽæ¯”è¾ƒæ£€æŸ¥çš„ç›®æ ‡å€¼åªä¼šè®¡ç®—一次。和ifè¯å¥ä¸€æ ·ï¼Œswitchè¯å¥åœ¨æœ€åŽå¯ä»¥æŽ¥ä¸€ä¸ªelse代ç å—æ¥å¤„ç†æ²¡æœ‰åŒ¹é…的情况。在生æˆçš„Lua代ç ä¸ï¼Œè¿›è¡Œæ¯”较是使用==æ“作符完æˆçš„。switchè¯å¥ä¸ä¹Ÿå¯ä»¥ä½¿ç”¨èµ‹å€¼è¡¨è¾¾å¼æ¥å‚¨å˜ä¸´æ—¶å˜é‡å€¼ã€‚ |
2590 | 2991 | ||
2591 | ```moonscript | 2992 | ```moonscript |
2592 | name = "Dan" | 2993 | switch name := "Dan" |
2593 | switch name | ||
2594 | when "Robert" | 2994 | when "Robert" |
2595 | print "ä½ æ˜¯Robert" | 2995 | print "ä½ æ˜¯Robert" |
2596 | when "Dan", "Daniel" | 2996 | when "Dan", "Daniel" |
2597 | print "ä½ çš„åå—æ˜¯Dan" | 2997 | print "ä½ çš„åå—æ˜¯Dan" |
2598 | else | 2998 | else |
2599 | print "我ä¸çŸ¥é“ä½ çš„åå—" | 2999 | print "我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯#{name}" |
2600 | ``` | 3000 | ``` |
2601 | <YueDisplay> | 3001 | <YueDisplay> |
2602 | <pre> | 3002 | <pre> |
2603 | name = "Dan" | 3003 | switch name := "Dan" |
2604 | switch name | ||
2605 | when "Robert" | 3004 | when "Robert" |
2606 | print "ä½ æ˜¯Robert" | 3005 | print "ä½ æ˜¯Robert" |
2607 | when "Dan", "Daniel" | 3006 | when "Dan", "Daniel" |
2608 | print "ä½ çš„åå—æ˜¯Dan" | 3007 | print "ä½ çš„åå—æ˜¯Dan" |
2609 | else | 3008 | else |
2610 | print "我ä¸çŸ¥é“ä½ çš„åå—" | 3009 | print "我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯#{name}" |
2611 | </pre> | 3010 | </pre> |
2612 | </YueDisplay> | 3011 | </YueDisplay> |
2613 | 3012 | ||
@@ -2684,7 +3083,7 @@ else | |||
2684 | </pre> | 3083 | </pre> |
2685 | </YueDisplay> | 3084 | </YueDisplay> |
2686 | 3085 | ||
2687 | 值得注æ„的是,在生æˆLuaä»£ç æ—¶ï¼Œæˆ‘们è¦åšæ£€æŸ¥çš„ç›®æ ‡å˜é‡ä¼šæ”¾åœ¨==表达å¼çš„å³ä¾§ã€‚当您希望给whenåå¥çš„æ¯”较对象定义一个\_\_eq元方法æ¥é‡è½½åˆ¤æ–逻辑时,å¯èƒ½ä¼šæœ‰ç”¨ã€‚ | 3086 | 值得注æ„的是,在生æˆLuaä»£ç æ—¶ï¼Œæˆ‘们è¦åšæ£€æŸ¥çš„ç›®æ ‡å˜é‡ä¼šæ”¾åœ¨==表达å¼çš„å³ä¾§ã€‚å½“ä½ å¸Œæœ›ç»™whenåå¥çš„æ¯”较对象定义一个\_\_eq元方法æ¥é‡è½½åˆ¤æ–逻辑时,å¯èƒ½ä¼šæœ‰ç”¨ã€‚ |
2688 | 3087 | ||
2689 | ### è¡¨æ ¼åŒ¹é… | 3088 | ### è¡¨æ ¼åŒ¹é… |
2690 | 3089 | ||
@@ -2744,9 +3143,126 @@ switch item | |||
2744 | </pre> | 3143 | </pre> |
2745 | </YueDisplay> | 3144 | </YueDisplay> |
2746 | 3145 | ||
3146 | ä½ ä¹Ÿå¯ä»¥åŒ¹é…æ•°ç»„å…ƒç´ ã€è¡¨æ ¼å—æ®µï¼Œç”šè‡³ä½¿ç”¨æ•°ç»„æˆ–è¡¨æ ¼å—é¢é‡æ¥åŒ¹é…嵌套的结构。 | ||
3147 | |||
3148 | åŒ¹é…æ•°ç»„å…ƒç´ ã€‚ | ||
3149 | |||
3150 | ```moonscript | ||
3151 | switch tb | ||
3152 | when [1, 2, 3] | ||
3153 | print "1, 2, 3" | ||
3154 | when [1, b, 3] | ||
3155 | print "1, #{b}, 3" | ||
3156 | when [1, 2, b = 3] -- å˜é‡b有默认值 | ||
3157 | print "1, 2, #{b}" | ||
3158 | ``` | ||
3159 | <YueDisplay> | ||
3160 | <pre> | ||
3161 | switch tb | ||
3162 | when [1, 2, 3] | ||
3163 | print "1, 2, 3" | ||
3164 | when [1, b, 3] | ||
3165 | print "1, #{b}, 3" | ||
3166 | when [1, 2, b = 3] -- å˜é‡b有默认值 | ||
3167 | print "1, 2, #{b}" | ||
3168 | </pre> | ||
3169 | </YueDisplay> | ||
3170 | |||
3171 | 匹é…è¡¨æ ¼å—æ®µã€‚ | ||
3172 | |||
3173 | ```moonscript | ||
3174 | switch tb | ||
3175 | when success: true, :result | ||
3176 | print "æˆåŠŸ", result | ||
3177 | when success: false | ||
3178 | print "失败", result | ||
3179 | else | ||
3180 | print "æ— æ•ˆå€¼" | ||
3181 | ``` | ||
3182 | <YueDisplay> | ||
3183 | <pre> | ||
3184 | switch tb | ||
3185 | when success: true, :result | ||
3186 | print "æˆåŠŸ", result | ||
3187 | when success: false | ||
3188 | print "失败", result | ||
3189 | else | ||
3190 | print "æ— æ•ˆå€¼" | ||
3191 | </pre> | ||
3192 | </YueDisplay> | ||
3193 | |||
3194 | 匹é…åµŒå¥—çš„è¡¨æ ¼ç»“æž„ã€‚ | ||
3195 | |||
3196 | ```moonscript | ||
3197 | switch tb | ||
3198 | when data: {type: "success", :content} | ||
3199 | print "æˆåŠŸ", content | ||
3200 | when data: {type: "error", :content} | ||
3201 | print "失败", content | ||
3202 | else | ||
3203 | print "æ— æ•ˆå€¼" | ||
3204 | ``` | ||
3205 | <YueDisplay> | ||
3206 | <pre> | ||
3207 | switch tb | ||
3208 | when data: {type: "success", :content} | ||
3209 | print "æˆåŠŸ", content | ||
3210 | when data: {type: "error", :content} | ||
3211 | print "失败", content | ||
3212 | else | ||
3213 | print "æ— æ•ˆå€¼" | ||
3214 | </pre> | ||
3215 | </YueDisplay> | ||
3216 | |||
3217 | 匹é…è¡¨æ ¼æ•°ç»„ã€‚ | ||
3218 | |||
3219 | ```moonscript | ||
3220 | switch tb | ||
3221 | when [ | ||
3222 | {a: 1, b: 2} | ||
3223 | {a: 3, b: 4} | ||
3224 | {a: 5, b: 6} | ||
3225 | fourth | ||
3226 | ] | ||
3227 | print "åŒ¹é…æˆåŠŸ", fourth | ||
3228 | ``` | ||
3229 | <YueDisplay> | ||
3230 | <pre> | ||
3231 | switch tb | ||
3232 | when [ | ||
3233 | {a: 1, b: 2} | ||
3234 | {a: 3, b: 4} | ||
3235 | {a: 5, b: 6} | ||
3236 | fourth | ||
3237 | ] | ||
3238 | print "åŒ¹é…æˆåŠŸ", fourth | ||
3239 | </pre> | ||
3240 | </YueDisplay> | ||
3241 | |||
3242 | 匹é…一个列表并æ•èŽ·ç‰¹å®šèŒƒå›´å†…çš„å…ƒç´ ã€‚ | ||
3243 | |||
3244 | ```moonscript | ||
3245 | segments = ["admin", "users", "logs", "view"] | ||
3246 | switch segments | ||
3247 | when [...groups, resource, action] | ||
3248 | print "Group:", groups -- 打å°: {"admin", "users"} | ||
3249 | print "Resource:", resource -- 打å°: "logs" | ||
3250 | print "Action:", action -- 打å°: "view" | ||
3251 | ``` | ||
3252 | <YueDisplay> | ||
3253 | <pre> | ||
3254 | segments = ["admin", "users", "logs", "view"] | ||
3255 | switch segments | ||
3256 | when [...groups, resource, action] | ||
3257 | print "Group:", groups -- 打å°: {"admin", "users"} | ||
3258 | print "Resource:", resource -- 打å°: "logs" | ||
3259 | print "Action:", action -- 打å°: "view" | ||
3260 | </pre> | ||
3261 | </YueDisplay> | ||
3262 | |||
2747 | ## é¢å‘对象编程 | 3263 | ## é¢å‘对象编程 |
2748 | 3264 | ||
2749 | 在以下的示例ä¸ï¼Œæœˆä¹‹è„šæœ¬ç”Ÿæˆçš„Lua代ç å¯èƒ½çœ‹èµ·æ¥ä¼šå¾ˆå¤æ‚。所以最好主è¦å…³æ³¨æœˆä¹‹è„šæœ¬ä»£ç 层é¢çš„æ„ä¹‰ï¼Œç„¶åŽå¦‚果您想知é“关于é¢å‘å¯¹è±¡åŠŸèƒ½çš„å®žçŽ°ç»†èŠ‚ï¼Œå†æŸ¥çœ‹Lua代ç 。 | 3265 | 在以下的示例ä¸ï¼Œæœˆä¹‹è„šæœ¬ç”Ÿæˆçš„Lua代ç å¯èƒ½çœ‹èµ·æ¥ä¼šå¾ˆå¤æ‚。所以最好主è¦å…³æ³¨æœˆä¹‹è„šæœ¬ä»£ç 层é¢çš„æ„ä¹‰ï¼Œç„¶åŽå¦‚æžœä½ æƒ³çŸ¥é“关于é¢å‘å¯¹è±¡åŠŸèƒ½çš„å®žçŽ°ç»†èŠ‚ï¼Œå†æŸ¥çœ‹Lua代ç 。 |
2750 | 3266 | ||
2751 | 一个简å•的类: | 3267 | 一个简å•的类: |
2752 | 3268 | ||
@@ -3214,7 +3730,7 @@ x = class | |||
3214 | 3730 | ||
3215 | ### ç±»æ··åˆ | 3731 | ### ç±»æ··åˆ |
3216 | 3732 | ||
3217 | 您å¯ä»¥é€šè¿‡ä½¿ç”¨ `using` 关键嗿¥å®žçŽ°ç±»æ··åˆã€‚è¿™æ„å‘³ç€æ‚¨å¯ä»¥ä»Žä¸€ä¸ªæ™®é€š Lua è¡¨æ ¼æˆ–å·²å®šä¹‰çš„ç±»å¯¹è±¡ä¸ï¼Œå¤åˆ¶å‡½æ•°åˆ°æ‚¨åˆ›å»ºçš„æ–°ç±»ä¸ã€‚当您使用普通 Lua è¡¨æ ¼è¿›è¡Œç±»æ··åˆæ—¶ï¼Œæ‚¨æœ‰æœºä¼šç”¨è‡ªå·±çš„实现æ¥é‡å†™ç±»çš„索引方法(例如元方法 `__index`ï¼‰ã€‚ç„¶è€Œï¼Œå½“æ‚¨ä»Žä¸€ä¸ªç±»å¯¹è±¡åšæ··åˆæ—¶ï¼Œéœ€è¦æ³¨æ„的是该类对象的元方法将ä¸ä¼šè¢«å¤åˆ¶åˆ°æ–°ç±»ã€‚ | 3733 | ä½ å¯ä»¥é€šè¿‡ä½¿ç”¨ `using` 关键嗿¥å®žçŽ°ç±»æ··åˆã€‚è¿™æ„味ç€ä½ å¯ä»¥ä»Žä¸€ä¸ªæ™®é€š Lua è¡¨æ ¼æˆ–å·²å®šä¹‰çš„ç±»å¯¹è±¡ä¸ï¼Œå¤åˆ¶å‡½æ•°åˆ°ä½ 创建的新类ä¸ã€‚å½“ä½ ä½¿ç”¨æ™®é€š Lua è¡¨æ ¼è¿›è¡Œç±»æ··åˆæ—¶ï¼Œä½ 有机会用自己的实现æ¥é‡å†™ç±»çš„索引方法(例如元方法 `__index`ï¼‰ã€‚ç„¶è€Œï¼Œå½“ä½ ä»Žä¸€ä¸ªç±»å¯¹è±¡åšæ··åˆæ—¶ï¼Œéœ€è¦æ³¨æ„的是该类对象的元方法将ä¸ä¼šè¢«å¤åˆ¶åˆ°æ–°ç±»ã€‚ |
3218 | 3734 | ||
3219 | ```moonscript | 3735 | ```moonscript |
3220 | MyIndex = __index: var: 1 | 3736 | MyIndex = __index: var: 1 |
@@ -3316,22 +3832,22 @@ me = create_person "Leaf", [dad, mother, sister] | |||
3316 | 3832 | ||
3317 | 在æ¤ç”¨æ³•ä¸ï¼Œwithå¯ä»¥è¢«è§†ä¸ºK组åˆå(k-combinator)的一ç§ç‰¹æ®Šå½¢å¼ã€‚ | 3833 | 在æ¤ç”¨æ³•ä¸ï¼Œwithå¯ä»¥è¢«è§†ä¸ºK组åˆå(k-combinator)的一ç§ç‰¹æ®Šå½¢å¼ã€‚ |
3318 | 3834 | ||
3319 | 如果您想给表达å¼å¦å¤–起一个åç§°çš„è¯ï¼Œwithè¯å¥ä¸çš„表达å¼ä¹Ÿå¯ä»¥æ˜¯ä¸€ä¸ªèµ‹å€¼è¯å¥ã€‚ | 3835 | å¦‚æžœä½ æƒ³ç»™è¡¨è¾¾å¼å¦å¤–起一个åç§°çš„è¯ï¼Œwithè¯å¥ä¸çš„表达å¼ä¹Ÿå¯ä»¥æ˜¯ä¸€ä¸ªèµ‹å€¼è¯å¥ã€‚ |
3320 | 3836 | ||
3321 | ```moonscript | 3837 | ```moonscript |
3322 | with str = "ä½ å¥½" | 3838 | with str := "ä½ å¥½" |
3323 | print "原始:", str | 3839 | print "原始:", str |
3324 | print "大写:", \upper! | 3840 | print "大写:", \upper! |
3325 | ``` | 3841 | ``` |
3326 | <YueDisplay> | 3842 | <YueDisplay> |
3327 | <pre> | 3843 | <pre> |
3328 | with str = "ä½ å¥½" | 3844 | with str := "ä½ å¥½" |
3329 | print "原始:", str | 3845 | print "原始:", str |
3330 | print "大写:", \upper! | 3846 | print "大写:", \upper! |
3331 | </pre> | 3847 | </pre> |
3332 | </YueDisplay> | 3848 | </YueDisplay> |
3333 | 3849 | ||
3334 | 在withè¯å¥ä¸å¯ä»¥ä½¿ç”¨`[]`访问特殊键。 | 3850 | ä½ å¯ä»¥åœ¨ `with` è¯å¥ä¸ä½¿ç”¨ `[]` 访问特殊键。 |
3335 | 3851 | ||
3336 | ```moonscript | 3852 | ```moonscript |
3337 | with tb | 3853 | with tb |
@@ -3354,6 +3870,19 @@ with tb | |||
3354 | </pre> | 3870 | </pre> |
3355 | </YueDisplay> | 3871 | </YueDisplay> |
3356 | 3872 | ||
3873 | `with?` 是 `with` è¯æ³•的一个增强版本,引入了å˜åœ¨æ€§æ£€æŸ¥ï¼Œç”¨äºŽåœ¨ä¸æ˜¾å¼åˆ¤ç©ºçš„æƒ…况下安全访问å¯èƒ½ä¸º nil 的对象。 | ||
3874 | |||
3875 | ```moonscript | ||
3876 | with? obj | ||
3877 | print obj.name | ||
3878 | ``` | ||
3879 | <YueDisplay> | ||
3880 | <pre> | ||
3881 | with? obj | ||
3882 | print obj.name | ||
3883 | </pre> | ||
3884 | </YueDisplay> | ||
3885 | |||
3357 | ## do è¯å¥ | 3886 | ## do è¯å¥ |
3358 | 3887 | ||
3359 | 当用作è¯å¥æ—¶ï¼Œdoè¯å¥çš„作用就åƒåœ¨Luaä¸å·®ä¸å¤šã€‚ | 3888 | 当用作è¯å¥æ—¶ï¼Œdoè¯å¥çš„作用就åƒåœ¨Luaä¸å·®ä¸å¤šã€‚ |
@@ -3373,7 +3902,7 @@ print var -- 这里是nil | |||
3373 | </pre> | 3902 | </pre> |
3374 | </YueDisplay> | 3903 | </YueDisplay> |
3375 | 3904 | ||
3376 | 月之脚本的 **do** 也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚å…许您将多行代ç 的处ç†åˆå¹¶ä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶å°†doè¯å¥ä»£ç å—的最åŽä¸€ä¸ªè¯å¥ä½œä¸ºè¡¨è¾¾å¼è¿”回的结果。 | 3905 | 月之脚本的 **do** 也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚å…è®¸ä½ å°†å¤šè¡Œä»£ç 的处ç†åˆå¹¶ä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶å°†doè¯å¥ä»£ç å—的最åŽä¸€ä¸ªè¯å¥ä½œä¸ºè¡¨è¾¾å¼è¿”回的结果。 |
3377 | 3906 | ||
3378 | ```moonscript | 3907 | ```moonscript |
3379 | counter = do | 3908 | counter = do |
@@ -4332,8 +4861,8 @@ simplified: boolean | |||
4332 | 4861 | ||
4333 | ç‰ˆæƒ (c) 2017-2025 æŽç‘¾ \<dragon-fly@qq.com\> | 4862 | ç‰ˆæƒ (c) 2017-2025 æŽç‘¾ \<dragon-fly@qq.com\> |
4334 | 4863 | ||
4335 | 特æ¤å…费授予任何获得本软件副本和相关文档文件(下称“软件â€ï¼‰çš„人ä¸å—é™åˆ¶åœ°å¤„置该软件的æƒåˆ©ï¼ŒåŒ…括ä¸å—é™åˆ¶åœ°ä½¿ç”¨ã€å¤åˆ¶ã€ä¿®æ”¹ã€åˆå¹¶ã€å‘布ã€åˆ†å‘ã€è½¬æŽˆè®¸å¯å’Œ/或出售该软件副本,以åŠå†æŽˆæƒè¢«é…å‘了本软件的人如上的æƒåˆ©ï¼Œé¡»åœ¨ä¸‹åˆ—æ¡ä»¶ä¸‹ï¼š | 4864 | 特æ¤å…费授予任何获得本软件副本和相关文档文件(下称“软件â€ï¼‰çš„人ä¸å—é™åˆ¶åœ°å¤„置该软件的æƒåˆ©ï¼ŒåŒ…括ä¸å—é™åˆ¶åœ°ä½¿ç”¨ã€å¤åˆ¶ã€ä¿®æ”¹ã€åˆå¹¶ã€å‘布ã€åˆ†å‘ã€è½¬æŽˆè®¸å¯å’Œ/或出售该软件副本,以åŠå†æŽˆæƒè¢«é…å‘了本软件的人如上的æƒåˆ©ï¼Œé¡»åœ¨ä¸‹åˆ—æ¡ä»¶ä¸‹ï¼š |
4336 | 上述版æƒå£°æ˜Žå’Œæœ¬è®¸å¯å£°æ˜Žåº”包å«åœ¨è¯¥è½¯ä»¶çš„æ‰€æœ‰å‰¯æœ¬æˆ–实质æˆåˆ†ä¸ã€‚ | 4865 | 上述版æƒå£°æ˜Žå’Œæœ¬è®¸å¯å£°æ˜Žåº”包å«åœ¨è¯¥è½¯ä»¶çš„æ‰€æœ‰å‰¯æœ¬æˆ–实质æˆåˆ†ä¸ã€‚ |
4337 | 本软件是“如æ¤â€æä¾›çš„,没有任何形å¼çš„æ˜Žç¤ºæˆ–暗示的ä¿è¯ï¼ŒåŒ…括但ä¸é™äºŽå¯¹é€‚销性ã€ç‰¹å®šç”¨é€”的适用性和ä¸ä¾µæƒçš„ä¿è¯ã€‚åœ¨ä»»ä½•æƒ…å†µä¸‹ï¼Œä½œè€…æˆ–ç‰ˆæƒæŒæœ‰äººéƒ½ä¸å¯¹ä»»ä½•ç´¢èµ”ã€æŸå®³æˆ–å…¶ä»–è´£ä»»è´Ÿè´£ï¼Œæ— è®ºè¿™äº›è¿½è´£æ¥è‡ªåˆåŒã€ä¾µæƒæˆ–其它行为ä¸ï¼Œè¿˜æ˜¯äº§ç”ŸäºŽã€æºäºŽæˆ–æœ‰å…³äºŽæœ¬è½¯ä»¶ä»¥åŠæœ¬è½¯ä»¶çš„使用或其它处置。 | 4866 | 本软件是“如æ¤â€æä¾›çš„,没有任何形å¼çš„æ˜Žç¤ºæˆ–暗示的ä¿è¯ï¼ŒåŒ…括但ä¸é™äºŽå¯¹é€‚销性ã€ç‰¹å®šç”¨é€”的适用性和ä¸ä¾µæƒçš„ä¿è¯ã€‚åœ¨ä»»ä½•æƒ…å†µä¸‹ï¼Œä½œè€…æˆ–ç‰ˆæƒæŒæœ‰äººéƒ½ä¸å¯¹ä»»ä½•ç´¢èµ”ã€æŸå®³æˆ–å…¶ä»–è´£ä»»è´Ÿè´£ï¼Œæ— è®ºè¿™äº›è¿½è´£æ¥è‡ªåˆåŒã€ä¾µæƒæˆ–其它行为ä¸ï¼Œè¿˜æ˜¯äº§ç”ŸäºŽã€æºäºŽæˆ–æœ‰å…³äºŽæœ¬è½¯ä»¶ä»¥åŠæœ¬è½¯ä»¶çš„使用或其它处置。 |
4338 | 4867 | ||
4339 | <CompilerModal /> | 4868 | <CompilerModal /> |
@@ -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 | ||
15 | do | 15 | do |
16 | (data) <- http?.get "ajaxtest" | 16 | data <- http?.get "ajaxtest" |
17 | body[".result"]\html data | 17 | body[".result"]\html data |
18 | (processed) <- http.post "ajaxprocess", data | 18 | processed <- http.post "ajaxprocess", data |
19 | body[".result"]\append processed | 19 | body[".result"]\append processed |
20 | <- setTimeout 1000 | 20 | <- setTimeout 1000 |
21 | print "done" | 21 | print "done" |
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 674dfe4..b6250d0 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue | |||
@@ -94,7 +94,7 @@ do | |||
94 | -- | 94 | -- |
95 | 95 | ||
96 | do | 96 | do |
97 | with {a,b} = thing | 97 | with {a,b} := thing |
98 | print a, b | 98 | print a, b |
99 | 99 | ||
100 | 100 | ||
@@ -240,5 +240,43 @@ do | |||
240 | switch tb | 240 | switch tb |
241 | when {c: {<"abc">: meta_field = "def"}, <[[any string]]>: {d: abc = 123}, <'str'>: {e: def = {}}} | 241 | when {c: {<"abc">: meta_field = "def"}, <[[any string]]>: {d: abc = 123}, <'str'>: {e: def = {}}} |
242 | print meta_field, abc, def | 242 | print meta_field, abc, def |
243 | |||
244 | do | ||
245 | clients = ["VIP_Alice", "User_Bob", "User_Clara", "VIP_Eva"] | ||
246 | [vipStart, ...regulars, vipEnd] = clients | ||
247 | print vipStart -- "VIP_Alice" | ||
248 | print regulars -- {"User_Bob", "User_Clara"} | ||
249 | print vipEnd -- "VIP_Eva" | ||
250 | |||
251 | do | ||
252 | setupMeeting = (participants) -> | ||
253 | [chair, ..._, secretary] = participants | ||
254 | print chair, secretary | ||
255 | |||
256 | setupMeeting ["Alice", "Bob", "Charlie", "David"] | ||
257 | -- Output: Alice David | ||
258 | |||
259 | do | ||
260 | getTransactions = -> | ||
261 | { | ||
262 | {id: "T1", amount: 100} | ||
263 | {id: "T2", amount: 200} | ||
264 | {id: "T3", amount: 300} | ||
265 | } | ||
266 | |||
267 | :id, :amount = getTransactions![#] | ||
268 | assert id == "T3" | ||
269 | assert amount == 300 | ||
270 | |||
271 | do | ||
272 | [ | ||
273 | _ | ||
274 | ...middle | ||
275 | _ | ||
276 | ] = tb | ||
277 | |||
278 | do | ||
279 | {a, :abc, b, :def, ...sub, d, e} = tb | ||
280 | |||
243 | nil | 281 | nil |
244 | 282 | ||
diff --git a/spec/inputs/funcs.yue b/spec/inputs/funcs.yue index e647edc..6b1669b 100644 --- a/spec/inputs/funcs.yue +++ b/spec/inputs/funcs.yue | |||
@@ -193,4 +193,35 @@ do | |||
193 | func = (): -> check 123 | 193 | func = (): -> check 123 |
194 | print func! -- get nil | 194 | print func! -- get nil |
195 | 195 | ||
196 | do | ||
197 | f = ({:a, :b, :c}) -> print a, b, c | ||
198 | f = (:a, :b, :c) -> print a, b, c | ||
199 | g = (x, :y) -> print x, y | ||
200 | i = ({a: ax = 0, b: by = 0}) -> print ax, by | ||
201 | j = (name, {id: uid = "n/a", :role = "guest"}) -> print name, uid, role | ||
202 | m = ({user: {:name, :age}, meta: {:ver = 1}}) -> print name, age, ver | ||
203 | m1 = ({user: {:name, :age}, :meta = {}}) -> print name, age, meta and meta.ver or "nil" | ||
204 | new = ({:name = "anon", :age = 0}) => | ||
205 | @name = name | ||
206 | @age = age | ||
207 | set = ({:name = @name, :age = @age}) => | ||
208 | @name = name | ||
209 | @age = age | ||
210 | logKV = ({:k, :v}, ...) -> | ||
211 | print "kv:", k, v | ||
212 | print "rest count:", select "#", ... | ||
213 | macro gen = (fname) -> | | ||
214 | #{fname} = ({:a, :b = 0}) -> print a, b | ||
215 | $gen foo | ||
216 | t1 = (:a, x) -> print a, x | ||
217 | t2 = (:a) -> print a | ||
218 | w = ( | ||
219 | id | ||
220 | {:x = 0, :y = 0} | ||
221 | :flag | ||
222 | ) -> | ||
223 | print id, x, y, flag | ||
224 | g1 = ({:a, a: ax}) -> print a, ax | ||
225 | g4 = ({:a, :b, ...rest}) -> print a, b | ||
226 | |||
196 | nil | 227 | nil |
diff --git a/spec/inputs/global.yue b/spec/inputs/global.yue index ce1cc15..4e3b8aa 100644 --- a/spec/inputs/global.yue +++ b/spec/inputs/global.yue | |||
@@ -82,3 +82,9 @@ do | |||
82 | FooBar = "pascal case" | 82 | FooBar = "pascal case" |
83 | FOOBAR = "all uppercase" | 83 | FOOBAR = "all uppercase" |
84 | 84 | ||
85 | do | ||
86 | global const class A | ||
87 | global const Flag = 1 | ||
88 | global const const, x, y = "const", 1, 2 | ||
89 | global const math, table | ||
90 | |||
diff --git a/spec/inputs/import.yue b/spec/inputs/import.yue index b8ffc24..8982e6c 100644 --- a/spec/inputs/import.yue +++ b/spec/inputs/import.yue | |||
@@ -139,3 +139,13 @@ do | |||
139 | import "m" as {c: d} | 139 | import "m" as {c: d} |
140 | import "m" as {g, {<close>: i}} | 140 | import "m" as {g, {<close>: i}} |
141 | 141 | ||
142 | do | ||
143 | import require | ||
144 | import string as stringlib | ||
145 | import string.format | ||
146 | import io.read as io_read | ||
147 | |||
148 | type = -> | ||
149 | import type as tp | ||
150 | import 月 as yue | ||
151 | |||
diff --git a/spec/inputs/lists.yue b/spec/inputs/lists.yue index 921cae0..c493b68 100644 --- a/spec/inputs/lists.yue +++ b/spec/inputs/lists.yue | |||
@@ -87,4 +87,51 @@ do | |||
87 | [a, b] = hello | 87 | [a, b] = hello |
88 | [name = "nameless", job = "jobless"] = person | 88 | [name = "nameless", job = "jobless"] = person |
89 | 89 | ||
90 | do | ||
91 | transactions = ["T001", "T002", "T003", "T004", "T005"] | ||
92 | middleTransactions = transactions[2, -2] | ||
93 | print middleTransactions -- => {"T002", "T003", "T004"} | ||
94 | |||
95 | do | ||
96 | logs = | ||
97 | - start: 0, end: 100 | ||
98 | - start: 100, end: 200 | ||
99 | - start: 200, end: 123 | ||
100 | print logs[#].end -- => 123 | ||
101 | |||
102 | do | ||
103 | pendingOrders = ["O001", "O002", "O003", "O004"] | ||
104 | print pendingOrders[# - 1] -- => "O003" | ||
105 | |||
106 | do | ||
107 | getOrders = -> | ||
108 | { | ||
109 | { id: "O1001", status: "pending" } | ||
110 | { id: "O1002", status: "processing" } | ||
111 | { id: "O1003", status: "done" } | ||
112 | } | ||
113 | |||
114 | lastStatus = getOrders()[#].status | ||
115 | assert lastStatus == "done" | ||
116 | |||
117 | do | ||
118 | cloneList1 = (list) -> list[,] | ||
119 | cloneList2 = (list) -> [...list,] | ||
120 | cloneTable = (tb) -> {...tb} | ||
121 | |||
122 | do | ||
123 | print( | ||
124 | globalTB[#] | ||
125 | a.b.c[# - 2] | ||
126 | x?\y?!.z?[# - 3] | ||
127 | ) | ||
128 | |||
129 | do | ||
130 | f = -> | ||
131 | print( | ||
132 | globalTB[#]\end 123 | ||
133 | a.b.c[5,-5][# - 2] | ||
134 | x?\y?!.z?[# - 3]?[, -3] | ||
135 | ) | ||
136 | |||
90 | nil | 137 | nil |
diff --git a/spec/inputs/loops.yue b/spec/inputs/loops.yue index c5b28b3..5df10ca 100644 --- a/spec/inputs/loops.yue +++ b/spec/inputs/loops.yue | |||
@@ -213,3 +213,55 @@ do | |||
213 | do | 213 | do |
214 | until x := func 'a', b do | 214 | until x := func 'a', b do |
215 | print "false expected" | 215 | print "false expected" |
216 | |||
217 | do | ||
218 | index = for i = 1, #tb | ||
219 | break i if tb[i] | ||
220 | |||
221 | f for i = 1, #tb | ||
222 | break i if tb[i] | ||
223 | |||
224 | f for i = 1, #tb | ||
225 | i if tb[i] | ||
226 | |||
227 | i = 1 | ||
228 | ids = while tb[i] | ||
229 | i += 1 | ||
230 | i - 1 | ||
231 | |||
232 | i = 1 | ||
233 | idx = while tb[i] | ||
234 | i += 1 | ||
235 | break i - 1 | ||
236 | |||
237 | f1 = -> | ||
238 | i = 1 | ||
239 | f while tb[i] | ||
240 | i += 1 | ||
241 | i - 1 | ||
242 | |||
243 | i = 1 | ||
244 | f while tb[i] | ||
245 | i += 1 | ||
246 | break i - 1 | ||
247 | |||
248 | list = for item in *items | ||
249 | switch item | ||
250 | when type: "A", :value | ||
251 | if value > 5 | ||
252 | item | ||
253 | |||
254 | do | ||
255 | repeat print 1 until true | ||
256 | |||
257 | x = repeat | ||
258 | a = func! | ||
259 | break a.x | ||
260 | until a.v | ||
261 | |||
262 | items = repeat | ||
263 | item = getItem! | ||
264 | break unless item | ||
265 | item if item.value > 0 | ||
266 | until false | ||
267 | |||
diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue index 5d5f1a9..191f09f 100644 --- a/spec/inputs/macro.yue +++ b/spec/inputs/macro.yue | |||
@@ -60,6 +60,11 @@ macro NumAndStr = (num, str) -> | |||
60 | 60 | ||
61 | print $NumAndStr 123, 'xyz' | 61 | print $NumAndStr 123, 'xyz' |
62 | 62 | ||
63 | macro NumAndStr2 = (num`Num, str`SingleString) -> | | ||
64 | [#{num}, #{str}] | ||
65 | |||
66 | print $NumAndStr2 456, 'abc' | ||
67 | |||
63 | $asserts item == nil | 68 | $asserts item == nil |
64 | 69 | ||
65 | $myconfig false | 70 | $myconfig false |
@@ -100,13 +105,14 @@ macro filter = (items, action)-> | |||
100 | $showMacro "filter", "[_ for _ in *#{items} when #{action}]" | 105 | $showMacro "filter", "[_ for _ in *#{items} when #{action}]" |
101 | 106 | ||
102 | macro reduce = (items, def, action)-> | 107 | macro reduce = (items, def, action)-> |
103 | $showMacro "reduce", "if ##{items} == 0 | 108 | $showMacro "reduce", | |
104 | #{def} | 109 | if ##{items} == 0 |
105 | else | 110 | #{def} |
106 | _1 = #{def} | 111 | else |
107 | for _2 in *#{items} | 112 | _1 = #{def} |
108 | _1 = #{action} | 113 | for _2 in *#{items} |
109 | _1" | 114 | _1 = #{action} |
115 | _1 | ||
110 | 116 | ||
111 | macro foreach = (items, action)-> | 117 | macro foreach = (items, action)-> |
112 | $showMacro "foreach", "for _ in *#{items} | 118 | $showMacro "foreach", "for _ in *#{items} |
@@ -154,13 +160,15 @@ macro curry = (...)-> | |||
154 | f = $curry x,y,z,do | 160 | f = $curry x,y,z,do |
155 | print x,y,z | 161 | print x,y,z |
156 | 162 | ||
157 | macro get_inner = (var)-> "do | 163 | macro get_inner = (var)-> | |
158 | a = 1 | 164 | do |
159 | a + 1" | 165 | a = 1 |
166 | a + 1 | ||
160 | 167 | ||
161 | macro get_inner_hygienic = (var)-> "(-> | 168 | macro get_inner_hygienic = (var)-> | |
162 | local a = 1 | 169 | (-> |
163 | a + 1)!" | 170 | local a = 1 |
171 | a + 1)! | ||
164 | 172 | ||
165 | do | 173 | do |
166 | a = 8 | 174 | a = 8 |
@@ -196,6 +204,18 @@ end | |||
196 | 204 | ||
197 | print x | 205 | print x |
198 | 206 | ||
207 | import "yue" | ||
208 | macro lua = (code`YAMLMultiline) -> { | ||
209 | code: yue.loadstring(code)! | ||
210 | type: "lua" | ||
211 | } | ||
212 | |||
213 | $lua | | ||
214 | local function f2(a) | ||
215 | return a + 1 | ||
216 | end | ||
217 | x = x + f2(3) | ||
218 | |||
199 | macro def = (fname, ...)-> | 219 | macro def = (fname, ...)-> |
200 | args = {...} | 220 | args = {...} |
201 | last = table.remove args | 221 | last = table.remove args |
@@ -317,7 +337,13 @@ $chainC( | |||
317 | Destroy! | 337 | Destroy! |
318 | ) | 338 | ) |
319 | 339 | ||
320 | macro tb = -> "{'abc', a:123, <call>:=> 998}" | 340 | macro tb = -> | |
341 | { | ||
342 | 'abc' | ||
343 | a: 123 | ||
344 | <call>: => 998 | ||
345 | } | ||
346 | |||
321 | print $tb[1], $tb.a, ($tb)!, $tb! | 347 | print $tb[1], $tb.a, ($tb)!, $tb! |
322 | 348 | ||
323 | print "current line: #{ $LINE }" | 349 | print "current line: #{ $LINE }" |
diff --git a/spec/inputs/macro_export.yue b/spec/inputs/macro_export.yue index cc7d459..22905b5 100644 --- a/spec/inputs/macro_export.yue +++ b/spec/inputs/macro_export.yue | |||
@@ -8,13 +8,12 @@ export macro config = (debugging = true)-> | |||
8 | "" | 8 | "" |
9 | 9 | ||
10 | export macro showMacro = (name, res)-> | 10 | export macro showMacro = (name, res)-> |
11 | if debugMacro then " | 11 | if debugMacro then | |
12 | do | 12 | do |
13 | txt = #{res} | 13 | txt = #{res} |
14 | print '[macro ' .. #{name} .. ']' | 14 | print '[macro #{name}]' |
15 | print txt | 15 | print txt |
16 | txt | 16 | txt |
17 | " | ||
18 | else | 17 | else |
19 | res | 18 | res |
20 | 19 | ||
@@ -35,14 +34,16 @@ export macro copy = (src, dst, ...)-> | |||
35 | src != "_src_" and src != "_dst_" and dst != "_src_" and dst != "_dst_" | 34 | src != "_src_" and src != "_dst_" and dst != "_src_" and dst != "_dst_" |
36 | "copy targets can not be _src_ or _dst_" | 35 | "copy targets can not be _src_ or _dst_" |
37 | ) | 36 | ) |
38 | " | 37 | copyFields = table.concat( |
39 | do | 38 | ["_dst_.#{field} = _src_.#{field}" for field in *{...}] |
40 | local _src_, _dst_ | 39 | "\n\t\t\t" |
41 | with _dst_ = #{dst} | 40 | ) |
42 | with _src_ = #{src} | 41 | | |
43 | #{table.concat for field in *{...} do " | 42 | do |
44 | _dst_.#{field} = _src_.#{field} | 43 | local _src_, _dst_ |
45 | "}" | 44 | with _dst_ := #{dst} |
45 | with _src_ := #{src} | ||
46 | #{copyFields} | ||
46 | 47 | ||
47 | export macro enum = (...) -> | 48 | export macro enum = (...) -> |
48 | items = {...} | 49 | items = {...} |
diff --git a/spec/inputs/macro_teal.yue b/spec/inputs/macro_teal.yue index 0cfd862..e51bcd7 100644 --- a/spec/inputs/macro_teal.yue +++ b/spec/inputs/macro_teal.yue | |||
@@ -4,11 +4,16 @@ $ -> | |||
4 | options.target_extension = "tl" | 4 | options.target_extension = "tl" |
5 | package.path ..= ";./spec/lib/?.lua" | 5 | package.path ..= ";./spec/lib/?.lua" |
6 | 6 | ||
7 | macro to_lua = (code)-> | 7 | macro to_lua = (code)-> | |
8 | "require('yue').to_lua(#{code}, reserve_line_number:false, same_module:true)" | 8 | require('yue').to_lua #{code}, |
9 | reserve_line_number: false | ||
10 | same_module: true | ||
9 | 11 | ||
10 | macro trim = (name)-> | 12 | macro trim = (name)-> | |
11 | "if result := #{name}\\match '[\\'\"](.*)[\\'\"]' then result else #{name}" | 13 | if result := #{name}\match '[\'"](.*)[\'"]' |
14 | result | ||
15 | else | ||
16 | #{name} | ||
12 | 17 | ||
13 | export macro local = (decl, value = nil)-> | 18 | export macro local = (decl, value = nil)-> |
14 | import "yue" as {options:{:tl_enabled}} | 19 | import "yue" as {options:{:tl_enabled}} |
diff --git a/spec/inputs/macro_todo.yue b/spec/inputs/macro_todo.yue index 752c9cb..c9c8f77 100644 --- a/spec/inputs/macro_todo.yue +++ b/spec/inputs/macro_todo.yue | |||
@@ -5,9 +5,6 @@ export macro todoInner = (module, line, msg)-> | |||
5 | type: "lua" | 5 | type: "lua" |
6 | } | 6 | } |
7 | 7 | ||
8 | export macro todo = (msg)-> | 8 | export macro todo = (msg)-> | |
9 | if msg | 9 | $todoInner $FILE, $LINE#{msg and ", #{msg}" or ""} |
10 | "$todoInner $FILE, $LINE, #{msg}" | ||
11 | else | ||
12 | "$todoInner $FILE, $LINE" | ||
13 | 10 | ||
diff --git a/spec/inputs/props.yue b/spec/inputs/props.yue new file mode 100644 index 0000000..bbb7aae --- /dev/null +++ b/spec/inputs/props.yue | |||
@@ -0,0 +1,61 @@ | |||
1 | class Props | ||
2 | __index: (name): nil => | ||
3 | cls = @.<> | ||
4 | if item := cls.__getter?[name] -- access properties | ||
5 | return item @ | ||
6 | elseif item := rawget cls, name -- access member functions | ||
7 | return item | ||
8 | else | ||
9 | c = cls | ||
10 | while c := c.<> -- recursive to access base classes | ||
11 | if item := c.__getter?[name] | ||
12 | cls.__getter ??= {} | ||
13 | cls.__getter[name] = item -- cache base properties to class | ||
14 | return item @ | ||
15 | elseif item := rawget c, name | ||
16 | rawset cls, name, item -- cache base member to class | ||
17 | return item | ||
18 | |||
19 | __newindex: (name, value) => | ||
20 | cls = @.<> | ||
21 | if item := cls.__setter?[name] -- access properties | ||
22 | item @, value | ||
23 | else | ||
24 | c = cls | ||
25 | while c := c.<> -- recursive to access base classes | ||
26 | if item := c.__setter?[name] | ||
27 | cls.__setter ??= {} | ||
28 | cls.__setter[name] = item -- cache base property to class | ||
29 | item @, value | ||
30 | return | ||
31 | rawset @, name, value -- assign field to self | ||
32 | |||
33 | assignReadOnly = -> error "assigning a readonly property" | ||
34 | |||
35 | prop: (name, props) => | ||
36 | { | ||
37 | :get | ||
38 | :set = assignReadOnly | ||
39 | } = props | ||
40 | if getter := rawget @__base, "__getter" | ||
41 | getter[name] = get | ||
42 | else | ||
43 | rawset @__base, "__getter", [name]: get | ||
44 | if setter := rawget @__base, "__setter" | ||
45 | setter[name] = set | ||
46 | else | ||
47 | rawset @__base, "__setter", [name]: set | ||
48 | |||
49 | class A extends Props | ||
50 | @prop 'x' | ||
51 | get: => @_x + 1000 | ||
52 | set: (v) => @_x = v | ||
53 | new: => | ||
54 | @_x = 0 | ||
55 | |||
56 | class B extends A | ||
57 | @prop 'abc', get: => "hello" | ||
58 | |||
59 | b = B! | ||
60 | b.x = 999 | ||
61 | print b.x, b.abc | ||
diff --git a/spec/inputs/string.yue b/spec/inputs/string.yue index f91383e..1f0fba8 100644 --- a/spec/inputs/string.yue +++ b/spec/inputs/string.yue | |||
@@ -74,3 +74,76 @@ _ = "hello" | |||
74 | something"hello"\world! | 74 | something"hello"\world! |
75 | something "hello"\world! | 75 | something "hello"\world! |
76 | 76 | ||
77 | do | ||
78 | str = | | ||
79 | key: value | ||
80 | str = | | ||
81 | config: | ||
82 | enabled: true | ||
83 | level: 5 | ||
84 | str = | | ||
85 | header: start | ||
86 | |||
87 | footer: end | ||
88 | str = | | ||
89 | name: #{username} | ||
90 | str = | | ||
91 | count: #{total} items | ||
92 | str = | | ||
93 | user: #{name} | ||
94 | id: #{id} | ||
95 | str = | | ||
96 | path: "C:\\Program Files\\App" | ||
97 | desc: 'single "quote" test' | ||
98 | str = | | ||
99 | key: value | ||
100 | next: 123 | ||
101 | str = | | ||
102 | list: | ||
103 | - "one" | ||
104 | - "two" | ||
105 | str = | | ||
106 | -- comment | ||
107 | content text | ||
108 | -- comment | ||
109 | str = | | ||
110 | #{1 + 2} | ||
111 | #{2 + 3} | ||
112 | #{"a" .. "b"} | ||
113 | obj = | ||
114 | settings: | | ||
115 | mode: #{mode} | ||
116 | flags: | ||
117 | - #{flag1} | ||
118 | - default | ||
119 | fn = -> | | ||
120 | Hello | ||
121 | name: #{userName} | ||
122 | str = | | ||
123 | result: | ||
124 | status: #{if ok then "pass" else "fail"} | ||
125 | code: #{code} | ||
126 | summary = | | ||
127 | date: #{os.date()} | ||
128 | values: | ||
129 | - | ||
130 | a: #{aVal} | ||
131 | b: #{bVal or defaultB} | ||
132 | msg = send | | ||
133 | Hello, #{user}! | ||
134 | Today is #{os.date("%A")}. | ||
135 | desc = do | ||
136 | prefix = "Result" | ||
137 | | | ||
138 | #{prefix}: | ||
139 | value: #{compute!} | ||
140 | (| | ||
141 | 1 | ||
142 | 2 | ||
143 | 3 | ||
144 | |||
145 | |||
146 | export yaml = | | ||
147 | version: #{ver} | ||
148 | ok: true | ||
149 | |||
diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue index 49d47f3..2b0669c 100644 --- a/spec/inputs/switch.yue +++ b/spec/inputs/switch.yue | |||
@@ -165,5 +165,128 @@ do | |||
165 | print item | 165 | print item |
166 | when [a = 1, b = "abc"] | 166 | when [a = 1, b = "abc"] |
167 | print a, b | 167 | print a, b |
168 | nil | ||
169 | 168 | ||
169 | do | ||
170 | switch tb | ||
171 | when [1, 2, 3] | ||
172 | print "1, 2, 3" | ||
173 | when [1, b, 3] | ||
174 | print "1, #{b}, 3" | ||
175 | when [1, 2, b = 3] | ||
176 | print "1, 2, #{b}" | ||
177 | |||
178 | do | ||
179 | switch tb | ||
180 | when success: true, :result | ||
181 | print "success", result | ||
182 | when success: false | ||
183 | print "failed", result | ||
184 | else | ||
185 | print "invalid" | ||
186 | |||
187 | do | ||
188 | switch tb | ||
189 | when {type: "success", :content} | ||
190 | print "success", content | ||
191 | when {type: "error", :content} | ||
192 | print "failed", content | ||
193 | else | ||
194 | print "invalid" | ||
195 | |||
196 | do | ||
197 | switch tb | ||
198 | when [ | ||
199 | {a: 1, b: 2} | ||
200 | {a: 3, b: 4} | ||
201 | {a: 5, b: 6} | ||
202 | fourth | ||
203 | ] | ||
204 | print "matched", fourth | ||
205 | |||
206 | switch tb | ||
207 | when [ | ||
208 | {c: 1, d: 2} | ||
209 | {c: 3, d: 4} | ||
210 | {c: 5, d: 6} | ||
211 | ] | ||
212 | print "OK" | ||
213 | when [ | ||
214 | _ | ||
215 | _ | ||
216 | {a: 1, b: 2} | ||
217 | {a: 3, b: 4} | ||
218 | {a: 5, b: 6} | ||
219 | sixth | ||
220 | ] | ||
221 | print "matched", sixth | ||
222 | |||
223 | do | ||
224 | switch v := "hello" | ||
225 | when "hello" | ||
226 | print "matched hello" | ||
227 | else | ||
228 | print "not matched" | ||
229 | -- output: matched hello | ||
230 | |||
231 | do | ||
232 | f = -> "ok" | ||
233 | switch val := f! | ||
234 | when "ok" | ||
235 | print "it's ok" | ||
236 | -- output: it's ok | ||
237 | |||
238 | |||
239 | do | ||
240 | g = -> 42 | ||
241 | switch result := g! | ||
242 | when 1, 2 | ||
243 | print "small" | ||
244 | when 42 | ||
245 | print "life universe everything" | ||
246 | else | ||
247 | print "other #{result}" | ||
248 | -- output: life universe everything | ||
249 | |||
250 | do | ||
251 | check = -> | ||
252 | if true | ||
253 | "yes" | ||
254 | else | ||
255 | "no" | ||
256 | |||
257 | switch x := check! | ||
258 | when "yes" | ||
259 | print "affirmative" | ||
260 | else | ||
261 | print "negative" | ||
262 | -- output: affirmative | ||
263 | |||
264 | do | ||
265 | t = (): tb -> | ||
266 | tb = {a: 1} | ||
267 | tb.a = 2 | ||
268 | |||
269 | switch data := t! | ||
270 | when {a: 2} | ||
271 | print "matched" | ||
272 | else | ||
273 | print "not matched" | ||
274 | |||
275 | do | ||
276 | clientData = ["Meta", "CUST_1001", "CHK123"] | ||
277 | switch clientData | ||
278 | when [...metadata, customerId, checksum] | ||
279 | print metadata -- {"Meta"} | ||
280 | print customerId -- "CUST_1001" | ||
281 | print checksum -- "CHK123" | ||
282 | |||
283 | do | ||
284 | handlePath = (segments) -> | ||
285 | switch segments | ||
286 | when [..._, resource, action] | ||
287 | print "Resource:", resource | ||
288 | print "Action:", action | ||
289 | |||
290 | handlePath ["admin", "logs", "view"] | ||
291 | |||
292 | nil | ||
diff --git a/spec/inputs/tables.yue b/spec/inputs/tables.yue index 0de8a8c..702e04a 100644 --- a/spec/inputs/tables.yue +++ b/spec/inputs/tables.yue | |||
@@ -245,6 +245,24 @@ menus = | |||
245 | click: -> | 245 | click: -> |
246 | } | 246 | } |
247 | 247 | ||
248 | _ = | ||
249 | boolean: | ||
250 | - true | ||
251 | - false | ||
252 | float: | ||
253 | - 3.14 | ||
254 | - -6.8523015e+5 | ||
255 | int: | ||
256 | - 123 | ||
257 | - -0b1010_0111_0100_1010_1110 | ||
258 | null: | ||
259 | nodeName: 'node' | ||
260 | parent: nil | ||
261 | string: | ||
262 | - 'Hello world' | ||
263 | - "newline | ||
264 | newline2" | ||
265 | |||
248 | tb = {...other} | 266 | tb = {...other} |
249 | 267 | ||
250 | tbMix = { | 268 | tbMix = { |
diff --git a/spec/inputs/try_catch.yue b/spec/inputs/try_catch.yue index 4e05bc6..6c29a52 100644 --- a/spec/inputs/try_catch.yue +++ b/spec/inputs/try_catch.yue | |||
@@ -62,6 +62,126 @@ f = -> | |||
62 | do | 62 | do |
63 | <- x | 63 | <- x |
64 | local tb, a, b, c | 64 | local tb, a, b, c |
65 | f = -> try tb.f a, b, c | 65 | f1 = -> try tb.f a, b, c |
66 | |||
67 | do | ||
68 | f1 = -> do | ||
69 | ok, ... = try func! | ||
70 | ... | ||
71 | |||
72 | do | ||
73 | local func | ||
74 | a, b, c = try? func! | ||
75 | |||
76 | do | ||
77 | a, b, c = try? func! | ||
78 | |||
79 | do | ||
80 | a = (try? func!) ?? "default" | ||
81 | |||
82 | do | ||
83 | f try? func! | ||
84 | |||
85 | do | ||
86 | f try? | ||
87 | print 123 | ||
88 | func! | ||
89 | catch e | ||
90 | print e | ||
91 | e | ||
66 | 92 | ||
67 | nil | 93 | nil |
94 | |||
95 | do | ||
96 | try | ||
97 | func 1, 2, 3 | ||
98 | catch err | ||
99 | print err | ||
100 | |||
101 | try func 1, 2, 3 | ||
102 | catch err | ||
103 | print err | ||
104 | |||
105 | try | ||
106 | print "trying" | ||
107 | func 1, 2, 3 | ||
108 | |||
109 | do | ||
110 | success, result = try | ||
111 | func 1, 2, 3 | ||
112 | catch err | ||
113 | print err | ||
114 | |||
115 | success, result = try func 1, 2, 3 | ||
116 | |||
117 | tb = {} | ||
118 | |||
119 | try tb.func | ||
120 | try tb.func! | ||
121 | try tb.func() | ||
122 | try (tb.func!) | ||
123 | try (tb\func(1, 2, 3)) | ||
124 | |||
125 | try tb.func 1 | ||
126 | try tb.func(1) | ||
127 | |||
128 | if (try func 1 | ||
129 | catch err | ||
130 | print err) | ||
131 | print "OK" | ||
132 | |||
133 | if try (func 1) | ||
134 | catch err | ||
135 | print err | ||
136 | print "OK" | ||
137 | |||
138 | do | ||
139 | if success, result := try func "abc", 123 | ||
140 | print result | ||
141 | |||
142 | success, result = try func "abc", 123 | ||
143 | catch err | ||
144 | print err | ||
145 | |||
146 | print result if success, result := try func "abc", 123 | ||
147 | catch err | ||
148 | print err | ||
149 | |||
150 | do | ||
151 | try | ||
152 | func 1, 2, 3 | ||
153 | |||
154 | try func 1, 2, 3 | ||
155 | |||
156 | do | ||
157 | <- x | ||
158 | local tb, a, b, c | ||
159 | f1 = -> try tb.f a, b, c | ||
160 | |||
161 | do | ||
162 | f1 = -> do | ||
163 | ok, ... = try func! | ||
164 | ... | ||
165 | |||
166 | do | ||
167 | local func | ||
168 | a, b, c = try? func! | ||
169 | |||
170 | do | ||
171 | a, b, c = try? func! | ||
172 | |||
173 | do | ||
174 | a = (try? func!) ?? "default" | ||
175 | |||
176 | do | ||
177 | f try? func! | ||
178 | |||
179 | do | ||
180 | f try? | ||
181 | print 123 | ||
182 | func! | ||
183 | catch e | ||
184 | print e | ||
185 | e | ||
186 | |||
187 | nil | ||
diff --git a/spec/inputs/unicode/destructure.yue b/spec/inputs/unicode/destructure.yue index 3c3a369..a5ffd5d 100644 --- a/spec/inputs/unicode/destructure.yue +++ b/spec/inputs/unicode/destructure.yue | |||
@@ -84,7 +84,7 @@ do | |||
84 | -- | 84 | -- |
85 | 85 | ||
86 | do | 86 | do |
87 | with {å…ƒç´ a,å…ƒç´ b} = 东西 | 87 | with {å…ƒç´ a,å…ƒç´ b} := 东西 |
88 | æ‰“å° å…ƒç´ a, å…ƒç´ b | 88 | æ‰“å° å…ƒç´ a, å…ƒç´ b |
89 | 89 | ||
90 | 90 | ||
diff --git a/spec/inputs/unicode/macro_export.yue b/spec/inputs/unicode/macro_export.yue index 3c9a942..56571cd 100644 --- a/spec/inputs/unicode/macro_export.yue +++ b/spec/inputs/unicode/macro_export.yue | |||
@@ -37,8 +37,8 @@ export macro å¤åˆ¶ = (æº, ç›®æ ‡, ...)-> | |||
37 | " | 37 | " |
38 | do | 38 | do |
39 | local _æº_, _ç›®æ ‡_ | 39 | local _æº_, _ç›®æ ‡_ |
40 | with _ç›®æ ‡_ = #{ç›®æ ‡} | 40 | with _ç›®æ ‡_ := #{ç›®æ ‡} |
41 | with _æº_ = #{æº} | 41 | with _æº_ := #{æº} |
42 | #{table.concat for å—æ®µ in *{...} do " | 42 | #{table.concat for å—æ®µ in *{...} do " |
43 | _ç›®æ ‡_.#{å—æ®µ} = _æº_.#{å—æ®µ} | 43 | _ç›®æ ‡_.#{å—æ®µ} = _æº_.#{å—æ®µ} |
44 | "}" | 44 | "}" |
diff --git a/spec/inputs/unicode/with.yue b/spec/inputs/unicode/with.yue index ecbfdab..3c15add 100644 --- a/spec/inputs/unicode/with.yue +++ b/spec/inputs/unicode/with.yue | |||
@@ -45,19 +45,19 @@ do | |||
45 | with å˜é‡a | 45 | with å˜é‡a |
46 | æ‰“å° .世界 | 46 | æ‰“å° .世界 |
47 | 47 | ||
48 | æ¨¡å— = with _æ¨¡å— = {} | 48 | æ¨¡å— = with _æ¨¡å— := {} |
49 | .事物 = "ä½ å¥½" | 49 | .事物 = "ä½ å¥½" |
50 | 50 | ||
51 | with å˜é‡a, å˜é‡b = 东西, 布 | 51 | with å˜é‡a, å˜é‡b := 东西, 布 |
52 | æ‰“å° .世界 | 52 | æ‰“å° .世界 |
53 | 53 | ||
54 | å˜é‡x = with å˜é‡a, å˜é‡b = 1, 2 | 54 | å˜é‡x = with å˜é‡a, å˜é‡b := 1, 2 |
55 | æ‰“å° å˜é‡a + å˜é‡b | 55 | æ‰“å° å˜é‡a + å˜é‡b |
56 | 56 | ||
57 | æ‰“å° with å˜é‡a, å˜é‡b = 1, 2 | 57 | æ‰“å° with å˜é‡a, å˜é‡b := 1, 2 |
58 | æ‰“å° å˜é‡a + å˜é‡b | 58 | æ‰“å° å˜é‡a + å˜é‡b |
59 | 59 | ||
60 | p = with ä½ å¥½!.å—æ®µx, 世界!.å—æ®µy = 1, 2 | 60 | p = with ä½ å¥½!.å—æ®µx, 世界!.å—æ®µy := 1, 2 |
61 | æ‰“å° å˜é‡a + å˜é‡b | 61 | æ‰“å° å˜é‡a + å˜é‡b |
62 | 62 | ||
63 | -- | 63 | -- |
@@ -68,16 +68,16 @@ do | |||
68 | å˜é‡x\大写! | 68 | å˜é‡x\大写! |
69 | 69 | ||
70 | do | 70 | do |
71 | with å˜é‡k = "ä¹”" | 71 | with å˜é‡k := "ä¹”" |
72 | æ‰“å° \大写! | 72 | æ‰“å° \大写! |
73 | 73 | ||
74 | do | 74 | do |
75 | with å˜é‡a,å˜é‡b,å˜é‡c = "", "", "" | 75 | with å˜é‡a,å˜é‡b,å˜é‡c := "", "", "" |
76 | æ‰“å° \大写! | 76 | æ‰“å° \大写! |
77 | 77 | ||
78 | do | 78 | do |
79 | å˜é‡a = "床铺" | 79 | å˜é‡a = "床铺" |
80 | with å˜é‡a,å˜é‡b,å˜é‡c = "", "", "" | 80 | with å˜é‡a,å˜é‡b,å˜é‡c := "", "", "" |
81 | æ‰“å° \大写! | 81 | æ‰“å° \大写! |
82 | 82 | ||
83 | do | 83 | do |
@@ -85,7 +85,7 @@ do | |||
85 | æ‰“å° \大写! | 85 | æ‰“å° \大写! |
86 | 86 | ||
87 | do | 87 | do |
88 | with å˜é‡k.å˜é‡j = "ä¹”" | 88 | with å˜é‡k.å˜é‡j := "ä¹”" |
89 | æ‰“å° \大写! | 89 | æ‰“å° \大写! |
90 | 90 | ||
91 | do | 91 | do |
@@ -96,7 +96,7 @@ do | |||
96 | 96 | ||
97 | do | 97 | do |
98 | with å˜é‡a | 98 | with å˜é‡a |
99 | with .b = 2 | 99 | with .b := 2 |
100 | æ‰“å° .c | 100 | æ‰“å° .c |
101 | 101 | ||
102 | do | 102 | do |
@@ -131,12 +131,12 @@ do | |||
131 | 131 | ||
132 | do | 132 | do |
133 | global 掩ç | 133 | global 掩ç |
134 | with? 掩ç = 实心矩形 宽: w, 高: h, 颜色: 0x66000000 | 134 | with? 掩ç := 实心矩形 宽: w, 高: h, 颜色: 0x66000000 |
135 | .触摸å¯ç”¨ = true | 135 | .触摸å¯ç”¨ = true |
136 | .åžå™¬è§¦æ‘¸ = true | 136 | .åžå™¬è§¦æ‘¸ = true |
137 | 137 | ||
138 | do | 138 | do |
139 | with? 掩ç = 实心矩形 宽: w, 高: h, 颜色: 0x66000000 | 139 | with? 掩ç := 实心矩形 宽: w, 高: h, 颜色: 0x66000000 |
140 | .触摸å¯ç”¨ = true | 140 | .触摸å¯ç”¨ = true |
141 | .åžå™¬è§¦æ‘¸ = true | 141 | .åžå™¬è§¦æ‘¸ = true |
142 | 142 | ||
diff --git a/spec/inputs/with.yue b/spec/inputs/with.yue index 19b7be1..2256833 100644 --- a/spec/inputs/with.yue +++ b/spec/inputs/with.yue | |||
@@ -48,21 +48,21 @@ do | |||
48 | with a -- only one value allowed | 48 | with a -- only one value allowed |
49 | print .world | 49 | print .world |
50 | 50 | ||
51 | mod = with _M = {} | 51 | mod = with _M := {} |
52 | .Thing = "hi" | 52 | .Thing = "hi" |
53 | 53 | ||
54 | -- operate on a only | 54 | -- operate on a only |
55 | with a, b = something, pooh | 55 | with a, b := something, pooh |
56 | print .world | 56 | print .world |
57 | 57 | ||
58 | x = with a, b = 1, 2 | 58 | x = with a, b := 1, 2 |
59 | print a + b | 59 | print a + b |
60 | 60 | ||
61 | print with a, b = 1, 2 | 61 | print with a, b := 1, 2 |
62 | print a + b | 62 | print a + b |
63 | 63 | ||
64 | -- assignment lhs must be evaluated in the order they appear | 64 | -- assignment lhs must be evaluated in the order they appear |
65 | p = with hello!.x, world!.y = 1, 2 | 65 | p = with hello!.x, world!.y := 1, 2 |
66 | print a + b | 66 | print a + b |
67 | 67 | ||
68 | -- | 68 | -- |
@@ -73,16 +73,16 @@ do | |||
73 | x\upper! | 73 | x\upper! |
74 | 74 | ||
75 | do | 75 | do |
76 | with k = "jo" | 76 | with k := "jo" |
77 | print \upper! | 77 | print \upper! |
78 | 78 | ||
79 | do | 79 | do |
80 | with a,b,c = "", "", "" | 80 | with a,b,c := "", "", "" |
81 | print \upper! | 81 | print \upper! |
82 | 82 | ||
83 | do | 83 | do |
84 | a = "bunk" | 84 | a = "bunk" |
85 | with a,b,c = "", "", "" | 85 | with a,b,c := "", "", "" |
86 | print \upper! | 86 | print \upper! |
87 | 87 | ||
88 | do | 88 | do |
@@ -90,7 +90,7 @@ do | |||
90 | print \upper! | 90 | print \upper! |
91 | 91 | ||
92 | do | 92 | do |
93 | with k.j = "jo" | 93 | with k.j := "jo" |
94 | print \upper! | 94 | print \upper! |
95 | 95 | ||
96 | do | 96 | do |
@@ -103,7 +103,7 @@ do | |||
103 | do | 103 | do |
104 | with a | 104 | with a |
105 | -- nested `with`s with assignments should change the scope correctly | 105 | -- nested `with`s with assignments should change the scope correctly |
106 | with .b = 2 | 106 | with .b := 2 |
107 | print .c | 107 | print .c |
108 | 108 | ||
109 | do | 109 | do |
@@ -138,12 +138,12 @@ do | |||
138 | 138 | ||
139 | do | 139 | do |
140 | global mask | 140 | global mask |
141 | with? mask = SolidRect width: w, height: h, color: 0x66000000 | 141 | with? mask := SolidRect width: w, height: h, color: 0x66000000 |
142 | .touchEnabled = true | 142 | .touchEnabled = true |
143 | .swallowTouches = true | 143 | .swallowTouches = true |
144 | 144 | ||
145 | do | 145 | do |
146 | with? mask = SolidRect width: w, height: h, color: 0x66000000 | 146 | with? mask := SolidRect width: w, height: h, color: 0x66000000 |
147 | .touchEnabled = true | 147 | .touchEnabled = true |
148 | .swallowTouches = true | 148 | .swallowTouches = true |
149 | 149 | ||
@@ -152,4 +152,22 @@ do | |||
152 | return with {} | 152 | return with {} |
153 | return [123] | 153 | return [123] |
154 | 154 | ||
155 | do | ||
156 | f with item | ||
157 | if .id > 0 | ||
158 | break .content | ||
159 | |||
160 | a = with tb | ||
161 | if .v | ||
162 | break .a | ||
163 | |||
164 | a = while true | ||
165 | break with? tb | ||
166 | break 1 | ||
167 | |||
168 | do | ||
169 | a = for i = 1, 100 | ||
170 | with? x := tb[i] | ||
171 | break x if .id := 1 | ||
172 | |||
155 | nil | 173 | nil |
diff --git a/spec/outputs/5.1/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 @@ | |||
1 | local _ = { | ||
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 | } | ||
44 | return nil | ||
diff --git a/spec/outputs/5.1/loops.lua b/spec/outputs/5.1/loops.lua index 57b19be..e4f2871 100644 --- a/spec/outputs/5.1/loops.lua +++ b/spec/outputs/5.1/loops.lua | |||
@@ -60,8 +60,8 @@ do | |||
60 | local y = hello[_index_0] | 60 | local y = hello[_index_0] |
61 | if y % 2 == 0 then | 61 | if y % 2 == 0 then |
62 | _accum_0[_len_0] = y | 62 | _accum_0[_len_0] = y |
63 | _len_0 = _len_0 + 1 | ||
63 | end | 64 | end |
64 | _len_0 = _len_0 + 1 | ||
65 | end | 65 | end |
66 | x = _accum_0 | 66 | x = _accum_0 |
67 | end | 67 | end |
@@ -132,13 +132,11 @@ do | |||
132 | end | 132 | end |
133 | do | 133 | do |
134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
135 | local _len_0 = 1 | ||
136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
138 | local thing = _list_2[_index_0] | 137 | local thing = _list_2[_index_0] |
139 | y = "hello" | 138 | y = "hello" |
140 | break | 139 | break |
141 | _len_0 = _len_0 + 1 | ||
142 | end | 140 | end |
143 | x = _accum_0 | 141 | x = _accum_0 |
144 | end | 142 | end |
@@ -489,3 +487,131 @@ do | |||
489 | end | 487 | end |
490 | until false | 488 | until false |
491 | end | 489 | end |
490 | local _anon_func_0 = function(i, tb) | ||
491 | local _accum_0 = { } | ||
492 | local _len_0 = 1 | ||
493 | while tb[i] do | ||
494 | i = i + 1 | ||
495 | _accum_0[_len_0] = i - 1 | ||
496 | _len_0 = _len_0 + 1 | ||
497 | end | ||
498 | return _accum_0 | ||
499 | end | ||
500 | do | ||
501 | local index | ||
502 | do | ||
503 | local _accum_0 | ||
504 | for i = 1, #tb do | ||
505 | if tb[i] then | ||
506 | _accum_0 = i | ||
507 | break | ||
508 | end | ||
509 | end | ||
510 | index = _accum_0 | ||
511 | end | ||
512 | f((function() | ||
513 | local _accum_0 | ||
514 | for i = 1, #tb do | ||
515 | if tb[i] then | ||
516 | _accum_0 = i | ||
517 | break | ||
518 | end | ||
519 | end | ||
520 | return _accum_0 | ||
521 | end)()) | ||
522 | f((function() | ||
523 | local _accum_0 = { } | ||
524 | local _len_0 = 1 | ||
525 | for i = 1, #tb do | ||
526 | if tb[i] then | ||
527 | _accum_0[_len_0] = i | ||
528 | _len_0 = _len_0 + 1 | ||
529 | end | ||
530 | end | ||
531 | return _accum_0 | ||
532 | end)()) | ||
533 | i = 1 | ||
534 | local ids | ||
535 | do | ||
536 | local _accum_0 = { } | ||
537 | local _len_0 = 1 | ||
538 | while tb[i] do | ||
539 | i = i + 1 | ||
540 | _accum_0[_len_0] = i - 1 | ||
541 | _len_0 = _len_0 + 1 | ||
542 | end | ||
543 | ids = _accum_0 | ||
544 | end | ||
545 | i = 1 | ||
546 | local idx | ||
547 | do | ||
548 | local _accum_0 | ||
549 | while tb[i] do | ||
550 | i = i + 1 | ||
551 | _accum_0 = i - 1 | ||
552 | break | ||
553 | end | ||
554 | idx = _accum_0 | ||
555 | end | ||
556 | local f1 | ||
557 | f1 = function() | ||
558 | i = 1 | ||
559 | return f(_anon_func_0(i, tb)) | ||
560 | end | ||
561 | i = 1 | ||
562 | f((function() | ||
563 | local _accum_0 | ||
564 | while tb[i] do | ||
565 | i = i + 1 | ||
566 | _accum_0 = i - 1 | ||
567 | break | ||
568 | end | ||
569 | return _accum_0 | ||
570 | end)()) | ||
571 | local _accum_0 = { } | ||
572 | local _len_0 = 1 | ||
573 | local _list_3 = items | ||
574 | for _index_0 = 1, #_list_3 do | ||
575 | local item = _list_3[_index_0] | ||
576 | local _type_0 = type(item) | ||
577 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
578 | if _tab_0 then | ||
579 | local value = item.value | ||
580 | if "A" == item.type and value ~= nil then | ||
581 | if value > 5 then | ||
582 | _accum_0[_len_0] = item | ||
583 | _len_0 = _len_0 + 1 | ||
584 | end | ||
585 | end | ||
586 | end | ||
587 | end | ||
588 | list = _accum_0 | ||
589 | end | ||
590 | do | ||
591 | repeat | ||
592 | print(1) | ||
593 | until true | ||
594 | do | ||
595 | local _accum_0 | ||
596 | repeat | ||
597 | a = func() | ||
598 | _accum_0 = a.x | ||
599 | break | ||
600 | until a.v | ||
601 | x = _accum_0 | ||
602 | end | ||
603 | local items | ||
604 | local _accum_0 = { } | ||
605 | local _len_0 = 1 | ||
606 | repeat | ||
607 | local item = getItem() | ||
608 | if not item then | ||
609 | break | ||
610 | end | ||
611 | if item.value > 0 then | ||
612 | _accum_0[_len_0] = item | ||
613 | _len_0 = _len_0 + 1 | ||
614 | end | ||
615 | until false | ||
616 | items = _accum_0 | ||
617 | end | ||
diff --git a/spec/outputs/5.1/try_catch.lua b/spec/outputs/5.1/try_catch.lua index efd92c6..d2b58bc 100644 --- a/spec/outputs/5.1/try_catch.lua +++ b/spec/outputs/5.1/try_catch.lua | |||
@@ -22,6 +22,43 @@ end | |||
22 | local _anon_func_7 = function(a, b, c, tb) | 22 | local _anon_func_7 = function(a, b, c, tb) |
23 | return tb.f(a, b, c) | 23 | return tb.f(a, b, c) |
24 | end | 24 | end |
25 | local _anon_func_8 = function(_arg_0, ...) | ||
26 | local ok = _arg_0 | ||
27 | return ... | ||
28 | end | ||
29 | local _anon_func_10 = function(_arg_0, ...) | ||
30 | local _ok_0 = _arg_0 | ||
31 | if _ok_0 then | ||
32 | return ... | ||
33 | end | ||
34 | end | ||
35 | local _anon_func_9 = function(func, pcall) | ||
36 | return _anon_func_10(pcall(func)) | ||
37 | end | ||
38 | local _anon_func_12 = function(_arg_0, ...) | ||
39 | local _ok_0 = _arg_0 | ||
40 | if _ok_0 then | ||
41 | return ... | ||
42 | end | ||
43 | end | ||
44 | local _anon_func_11 = function(func, pcall) | ||
45 | return _anon_func_12(pcall(func)) | ||
46 | end | ||
47 | local _anon_func_14 = function(_arg_0, ...) | ||
48 | local _ok_0 = _arg_0 | ||
49 | if _ok_0 then | ||
50 | return ... | ||
51 | end | ||
52 | end | ||
53 | local _anon_func_13 = function(func, print, xpcall) | ||
54 | return _anon_func_14(xpcall(function() | ||
55 | print(123) | ||
56 | return func() | ||
57 | end, function(e) | ||
58 | print(e) | ||
59 | return e | ||
60 | end)) | ||
61 | end | ||
25 | local f | 62 | local f |
26 | f = function() | 63 | f = function() |
27 | xpcall(function() | 64 | xpcall(function() |
@@ -104,10 +141,236 @@ f = function() | |||
104 | do | 141 | do |
105 | x(function() | 142 | x(function() |
106 | local tb, a, b, c | 143 | local tb, a, b, c |
107 | f = function() | 144 | local f1 |
145 | f1 = function() | ||
108 | return pcall(_anon_func_7, a, b, c, tb) | 146 | return pcall(_anon_func_7, a, b, c, tb) |
109 | end | 147 | end |
110 | end) | 148 | end) |
111 | end | 149 | end |
150 | do | ||
151 | local f1 | ||
152 | f1 = function() | ||
153 | do | ||
154 | return _anon_func_8(pcall(function() | ||
155 | return func() | ||
156 | end)) | ||
157 | end | ||
158 | end | ||
159 | end | ||
160 | do | ||
161 | local func | ||
162 | local a, b, c | ||
163 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
164 | if _ok_0 then | ||
165 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
166 | end | ||
167 | end | ||
168 | do | ||
169 | local a, b, c | ||
170 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
171 | return func() | ||
172 | end) | ||
173 | if _ok_0 then | ||
174 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
175 | end | ||
176 | end | ||
177 | do | ||
178 | local a | ||
179 | local _exp_0 = (_anon_func_9(func, pcall)) | ||
180 | if _exp_0 ~= nil then | ||
181 | a = _exp_0 | ||
182 | else | ||
183 | a = "default" | ||
184 | end | ||
185 | end | ||
186 | do | ||
187 | f(_anon_func_11(func, pcall)) | ||
188 | end | ||
189 | do | ||
190 | f(_anon_func_13(func, print, xpcall)) | ||
191 | end | ||
112 | return nil | 192 | return nil |
113 | end | 193 | end |
194 | local _anon_func_15 = function(a, b, c, tb) | ||
195 | return tb.f(a, b, c) | ||
196 | end | ||
197 | local _anon_func_16 = function(_arg_0, ...) | ||
198 | local ok = _arg_0 | ||
199 | return ... | ||
200 | end | ||
201 | do | ||
202 | xpcall(function() | ||
203 | return func(1, 2, 3) | ||
204 | end, function(err) | ||
205 | return print(err) | ||
206 | end) | ||
207 | xpcall(function() | ||
208 | return func(1, 2, 3) | ||
209 | end, function(err) | ||
210 | return print(err) | ||
211 | end) | ||
212 | pcall(function() | ||
213 | print("trying") | ||
214 | return func(1, 2, 3) | ||
215 | end) | ||
216 | do | ||
217 | local success, result = xpcall(function() | ||
218 | return func(1, 2, 3) | ||
219 | end, function(err) | ||
220 | return print(err) | ||
221 | end) | ||
222 | success, result = pcall(function() | ||
223 | return func(1, 2, 3) | ||
224 | end) | ||
225 | end | ||
226 | local tb = { } | ||
227 | pcall(function() | ||
228 | return tb.func | ||
229 | end) | ||
230 | pcall(function() | ||
231 | return tb.func() | ||
232 | end) | ||
233 | pcall(function() | ||
234 | return tb.func() | ||
235 | end) | ||
236 | pcall(function() | ||
237 | return (tb.func()) | ||
238 | end) | ||
239 | pcall(function() | ||
240 | return (tb:func(1, 2, 3)) | ||
241 | end) | ||
242 | pcall(function() | ||
243 | return tb.func(1) | ||
244 | end) | ||
245 | pcall(function() | ||
246 | return tb.func(1) | ||
247 | end) | ||
248 | if (xpcall(function() | ||
249 | return func(1) | ||
250 | end, function(err) | ||
251 | return print(err) | ||
252 | end)) then | ||
253 | print("OK") | ||
254 | end | ||
255 | if xpcall(function() | ||
256 | return (func(1)) | ||
257 | end, function(err) | ||
258 | return print(err) | ||
259 | end) then | ||
260 | print("OK") | ||
261 | end | ||
262 | do | ||
263 | do | ||
264 | local success, result = pcall(function() | ||
265 | return func("abc", 123) | ||
266 | end) | ||
267 | if success then | ||
268 | print(result) | ||
269 | end | ||
270 | end | ||
271 | local success, result = xpcall(function() | ||
272 | return func("abc", 123) | ||
273 | end, function(err) | ||
274 | return print(err) | ||
275 | end) | ||
276 | success, result = xpcall(function() | ||
277 | return func("abc", 123) | ||
278 | end, function(err) | ||
279 | return print(err) | ||
280 | end) | ||
281 | if success then | ||
282 | print(result) | ||
283 | end | ||
284 | end | ||
285 | do | ||
286 | pcall(function() | ||
287 | return func(1, 2, 3) | ||
288 | end) | ||
289 | pcall(function() | ||
290 | return func(1, 2, 3) | ||
291 | end) | ||
292 | end | ||
293 | do | ||
294 | x(function() | ||
295 | local tb, a, b, c | ||
296 | local f1 | ||
297 | f1 = function() | ||
298 | return pcall(_anon_func_15, a, b, c, tb) | ||
299 | end | ||
300 | end) | ||
301 | end | ||
302 | do | ||
303 | local f1 | ||
304 | f1 = function() | ||
305 | do | ||
306 | return _anon_func_16(pcall(function() | ||
307 | return func() | ||
308 | end)) | ||
309 | end | ||
310 | end | ||
311 | end | ||
312 | do | ||
313 | local func | ||
314 | local a, b, c | ||
315 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
316 | if _ok_0 then | ||
317 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
318 | end | ||
319 | end | ||
320 | do | ||
321 | local a, b, c | ||
322 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
323 | return func() | ||
324 | end) | ||
325 | if _ok_0 then | ||
326 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
327 | end | ||
328 | end | ||
329 | do | ||
330 | local a | ||
331 | local _exp_0 = ((function() | ||
332 | return (function(_arg_0, ...) | ||
333 | local _ok_0 = _arg_0 | ||
334 | if _ok_0 then | ||
335 | return ... | ||
336 | end | ||
337 | end)(pcall(function() | ||
338 | return func() | ||
339 | end)) | ||
340 | end)()) | ||
341 | if _exp_0 ~= nil then | ||
342 | a = _exp_0 | ||
343 | else | ||
344 | a = "default" | ||
345 | end | ||
346 | end | ||
347 | do | ||
348 | f((function() | ||
349 | return (function(_arg_0, ...) | ||
350 | local _ok_0 = _arg_0 | ||
351 | if _ok_0 then | ||
352 | return ... | ||
353 | end | ||
354 | end)(pcall(function() | ||
355 | return func() | ||
356 | end)) | ||
357 | end)()) | ||
358 | end | ||
359 | do | ||
360 | f((function() | ||
361 | return (function(_arg_0, ...) | ||
362 | local _ok_0 = _arg_0 | ||
363 | if _ok_0 then | ||
364 | return ... | ||
365 | end | ||
366 | end)(xpcall(function() | ||
367 | print(123) | ||
368 | return func() | ||
369 | end, function(e) | ||
370 | print(e) | ||
371 | return e | ||
372 | end)) | ||
373 | end)()) | ||
374 | end | ||
375 | end | ||
376 | return nil | ||
diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua index 162c5a8..89c5f8a 100644 --- a/spec/outputs/assign.lua +++ b/spec/outputs/assign.lua | |||
@@ -43,10 +43,8 @@ do | |||
43 | end | 43 | end |
44 | end | 44 | end |
45 | local _anon_func_0 = function(print) | 45 | local _anon_func_0 = function(print) |
46 | do | 46 | print(123) |
47 | print(123) | 47 | return { } |
48 | return { } | ||
49 | end | ||
50 | end | 48 | end |
51 | return _(function() | 49 | return _(function() |
52 | setmetatable(a, _anon_func_0(print)) | 50 | setmetatable(a, _anon_func_0(print)) |
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua index f6d5d61..055e79b 100644 --- a/spec/outputs/codes_from_doc.lua +++ b/spec/outputs/codes_from_doc.lua | |||
@@ -20,6 +20,38 @@ local inventory = { | |||
20 | } | 20 | } |
21 | } | 21 | } |
22 | } | 22 | } |
23 | local map | ||
24 | map = function(arr, action) | ||
25 | local _accum_0 = { } | ||
26 | local _len_0 = 1 | ||
27 | for _index_0 = 1, #arr do | ||
28 | local item = arr[_index_0] | ||
29 | _accum_0[_len_0] = action(item) | ||
30 | _len_0 = _len_0 + 1 | ||
31 | end | ||
32 | return _accum_0 | ||
33 | end | ||
34 | local filter | ||
35 | filter = function(arr, cond) | ||
36 | local _accum_0 = { } | ||
37 | local _len_0 = 1 | ||
38 | for _index_0 = 1, #arr do | ||
39 | local item = arr[_index_0] | ||
40 | if cond(item) then | ||
41 | _accum_0[_len_0] = item | ||
42 | _len_0 = _len_0 + 1 | ||
43 | end | ||
44 | end | ||
45 | return _accum_0 | ||
46 | end | ||
47 | local reduce | ||
48 | reduce = function(arr, init, action) | ||
49 | for _index_0 = 1, #arr do | ||
50 | local item = arr[_index_0] | ||
51 | init = action(init, item) | ||
52 | end | ||
53 | return init | ||
54 | end | ||
23 | print(reduce(filter(map({ | 55 | print(reduce(filter(map({ |
24 | 1, | 56 | 1, |
25 | 2, | 57 | 2, |
@@ -77,6 +109,12 @@ end | |||
77 | print("yuescript") | 109 | print("yuescript") |
78 | print(3) | 110 | print(3) |
79 | print("Valid enum type:", "Static") | 111 | print("Valid enum type:", "Static") |
112 | do | ||
113 | print(123, "hello") | ||
114 | end | ||
115 | do | ||
116 | print(123, "hello") | ||
117 | end | ||
80 | if tb ~= nil then | 118 | if tb ~= nil then |
81 | tb:func() | 119 | tb:func() |
82 | end | 120 | end |
@@ -177,6 +215,16 @@ for _key_0, _value_0 in pairs(b) do | |||
177 | end | 215 | end |
178 | end | 216 | end |
179 | merge = _tab_0 | 217 | merge = _tab_0 |
218 | local last | ||
219 | do | ||
220 | local _item_0 = data.items | ||
221 | last = _item_0[#_item_0] | ||
222 | end | ||
223 | local second_last | ||
224 | do | ||
225 | local _item_0 = data.items | ||
226 | second_last = _item_0[#_item_0 - 1] | ||
227 | end | ||
180 | local mt = { } | 228 | local mt = { } |
181 | local add | 229 | local add |
182 | add = function(self, right) | 230 | add = function(self, right) |
@@ -307,6 +355,14 @@ func({ | |||
307 | 2, | 355 | 2, |
308 | 3 | 356 | 3 |
309 | }) | 357 | }) |
358 | local f | ||
359 | f = function() | ||
360 | return { | ||
361 | 1, | ||
362 | 2, | ||
363 | 3 | ||
364 | } | ||
365 | end | ||
310 | local tb = { | 366 | local tb = { |
311 | name = "abc", | 367 | name = "abc", |
312 | values = { | 368 | values = { |
@@ -547,6 +603,59 @@ end | |||
547 | local two, four | 603 | local two, four |
548 | local _obj_0 = items | 604 | local _obj_0 = items |
549 | two, four = _obj_0[2], _obj_0[4] | 605 | two, four = _obj_0[2], _obj_0[4] |
606 | local orders = { | ||
607 | "first", | ||
608 | "second", | ||
609 | "third", | ||
610 | "fourth", | ||
611 | "last" | ||
612 | } | ||
613 | local first, bulk, last = orders[1], (function() | ||
614 | local _accum_0 = { } | ||
615 | local _len_0 = 1 | ||
616 | local _max_0 = #orders + -2 + 1 | ||
617 | for _index_0 = 2, _max_0 do | ||
618 | local _item_0 = orders[_index_0] | ||
619 | _accum_0[_len_0] = _item_0 | ||
620 | _len_0 = _len_0 + 1 | ||
621 | end | ||
622 | return _accum_0 | ||
623 | end)(), orders[#orders] | ||
624 | print(first) | ||
625 | print(bulk) | ||
626 | print(last) | ||
627 | local first, rest | ||
628 | do | ||
629 | local _obj_0 = orders | ||
630 | first, rest = _obj_0[1], (function() | ||
631 | local _accum_0 = { } | ||
632 | local _len_0 = 1 | ||
633 | local _max_0 = #_obj_0 | ||
634 | for _index_0 = 2, _max_0 do | ||
635 | local _item_0 = _obj_0[_index_0] | ||
636 | _accum_0[_len_0] = _item_0 | ||
637 | _len_0 = _len_0 + 1 | ||
638 | end | ||
639 | return _accum_0 | ||
640 | end)() | ||
641 | end | ||
642 | local start, last | ||
643 | do | ||
644 | local _obj_0 = orders | ||
645 | start, last = (function() | ||
646 | local _accum_0 = { } | ||
647 | local _len_0 = 1 | ||
648 | local _max_0 = #_obj_0 + -2 + 1 | ||
649 | for _index_0 = 1, _max_0 do | ||
650 | local _item_0 = _obj_0[_index_0] | ||
651 | _accum_0[_len_0] = _item_0 | ||
652 | _len_0 = _len_0 + 1 | ||
653 | end | ||
654 | return _accum_0 | ||
655 | end)(), _obj_0[#_obj_0] | ||
656 | end | ||
657 | local _obj_0 = orders | ||
658 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
550 | local tuples = { | 659 | local tuples = { |
551 | { | 660 | { |
552 | "hello", | 661 | "hello", |
@@ -648,6 +757,56 @@ end) | |||
648 | if success then | 757 | if success then |
649 | print(result) | 758 | print(result) |
650 | end | 759 | end |
760 | local a, b, c | ||
761 | do | ||
762 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
763 | return func() | ||
764 | end) | ||
765 | if _ok_0 then | ||
766 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
767 | end | ||
768 | end | ||
769 | do | ||
770 | local _exp_0 = ((function() | ||
771 | return (function(_arg_0, ...) | ||
772 | local _ok_0 = _arg_0 | ||
773 | if _ok_0 then | ||
774 | return ... | ||
775 | end | ||
776 | end)(pcall(function() | ||
777 | return func() | ||
778 | end)) | ||
779 | end)()) | ||
780 | if _exp_0 ~= nil then | ||
781 | a = _exp_0 | ||
782 | else | ||
783 | a = "default" | ||
784 | end | ||
785 | end | ||
786 | f((function() | ||
787 | return (function(_arg_0, ...) | ||
788 | local _ok_0 = _arg_0 | ||
789 | if _ok_0 then | ||
790 | return ... | ||
791 | end | ||
792 | end)(pcall(function() | ||
793 | return func() | ||
794 | end)) | ||
795 | end)()) | ||
796 | f((function() | ||
797 | return (function(_arg_0, ...) | ||
798 | local _ok_0 = _arg_0 | ||
799 | if _ok_0 then | ||
800 | return ... | ||
801 | end | ||
802 | end)(xpcall(function() | ||
803 | print(123) | ||
804 | return func() | ||
805 | end, function(e) | ||
806 | print(e) | ||
807 | return e | ||
808 | end)) | ||
809 | end)()) | ||
651 | local a <const> = 123 | 810 | local a <const> = 123 |
652 | local _ <close> = setmetatable({ }, { | 811 | local _ <close> = setmetatable({ }, { |
653 | __close = function() | 812 | __close = function() |
@@ -657,10 +816,19 @@ local _ <close> = setmetatable({ }, { | |||
657 | local a, b, c, d | 816 | local a, b, c, d |
658 | local _obj_0 = tb | 817 | local _obj_0 = tb |
659 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 818 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
819 | Constant = 123 | ||
660 | local some_string = "Here is a string\n that has a line break in it." | 820 | local some_string = "Here is a string\n that has a line break in it." |
661 | print("I am " .. tostring(math.random() * 100) .. "% sure.") | 821 | print("I am " .. tostring(math.random() * 100) .. "% sure.") |
662 | local integer = 1000000 | 822 | local integer = 1000000 |
663 | local hex = 0xEFBBBF | 823 | local hex = 0xEFBBBF |
824 | local binary = 19 | ||
825 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
826 | local fn | ||
827 | fn = function() | ||
828 | local str = "foo:\n bar: baz" | ||
829 | return str | ||
830 | end | ||
831 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
664 | local my_function | 832 | local my_function |
665 | my_function = function() end | 833 | my_function = function() end |
666 | my_function() | 834 | my_function() |
@@ -755,6 +923,36 @@ if func(1, 2, 3, "hello", "world") then | |||
755 | print("hello") | 923 | print("hello") |
756 | print("I am inside if") | 924 | print("I am inside if") |
757 | end | 925 | end |
926 | local f1 | ||
927 | f1 = function(_arg_0) | ||
928 | local a, b, c | ||
929 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
930 | return print(a, b, c) | ||
931 | end | ||
932 | f1({ | ||
933 | a = 1, | ||
934 | b = "2", | ||
935 | c = { } | ||
936 | }) | ||
937 | local f2 | ||
938 | f2 = function(_arg_0, c) | ||
939 | local a1, b | ||
940 | a1, b = _arg_0.a, _arg_0.b | ||
941 | if a1 == nil then | ||
942 | a1 = 123 | ||
943 | end | ||
944 | if b == nil then | ||
945 | b = 'abc' | ||
946 | end | ||
947 | if c == nil then | ||
948 | c = { } | ||
949 | end | ||
950 | return print(a1, b, c) | ||
951 | end | ||
952 | local arg1 = { | ||
953 | a = 0 | ||
954 | } | ||
955 | f2(arg1, arg2) | ||
758 | f(function() | 956 | f(function() |
759 | return print("hello") | 957 | return print("hello") |
760 | end) | 958 | end) |
@@ -970,8 +1168,7 @@ local slice | |||
970 | local _accum_0 = { } | 1168 | local _accum_0 = { } |
971 | local _len_0 = 1 | 1169 | local _len_0 = 1 |
972 | local _list_0 = items | 1170 | local _list_0 = items |
973 | local _max_0 = 5 | 1171 | for _index_0 = 1, 5 do |
974 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
975 | local item = _list_0[_index_0] | 1172 | local item = _list_0[_index_0] |
976 | _accum_0[_len_0] = item | 1173 | _accum_0[_len_0] = item |
977 | _len_0 = _len_0 + 1 | 1174 | _len_0 = _len_0 + 1 |
@@ -981,7 +1178,8 @@ local slice | |||
981 | local _accum_0 = { } | 1178 | local _accum_0 = { } |
982 | local _len_0 = 1 | 1179 | local _len_0 = 1 |
983 | local _list_0 = items | 1180 | local _list_0 = items |
984 | for _index_0 = 2, #_list_0 do | 1181 | local _max_0 = #_list_0 |
1182 | for _index_0 = 2, _max_0 do | ||
985 | local item = _list_0[_index_0] | 1183 | local item = _list_0[_index_0] |
986 | _accum_0[_len_0] = item | 1184 | _accum_0[_len_0] = item |
987 | _len_0 = _len_0 + 1 | 1185 | _len_0 = _len_0 + 1 |
@@ -991,12 +1189,46 @@ local slice | |||
991 | local _accum_0 = { } | 1189 | local _accum_0 = { } |
992 | local _len_0 = 1 | 1190 | local _len_0 = 1 |
993 | local _list_0 = items | 1191 | local _list_0 = items |
994 | for _index_0 = 1, #_list_0, 2 do | 1192 | local _max_0 = #_list_0 |
1193 | for _index_0 = 1, _max_0, 2 do | ||
995 | local item = _list_0[_index_0] | 1194 | local item = _list_0[_index_0] |
996 | _accum_0[_len_0] = item | 1195 | _accum_0[_len_0] = item |
997 | _len_0 = _len_0 + 1 | 1196 | _len_0 = _len_0 + 1 |
998 | end | 1197 | end |
999 | slice = _accum_0 | 1198 | slice = _accum_0 |
1199 | local slice | ||
1200 | local _accum_0 = { } | ||
1201 | local _len_0 = 1 | ||
1202 | local _list_0 = items | ||
1203 | local _min_0 = #_list_0 + -4 + 1 | ||
1204 | local _max_0 = #_list_0 + -1 + 1 | ||
1205 | for _index_0 = _min_0, _max_0 do | ||
1206 | local item = _list_0[_index_0] | ||
1207 | _accum_0[_len_0] = item | ||
1208 | _len_0 = _len_0 + 1 | ||
1209 | end | ||
1210 | slice = _accum_0 | ||
1211 | local reverse_slice | ||
1212 | local _accum_0 = { } | ||
1213 | local _len_0 = 1 | ||
1214 | local _list_0 = items | ||
1215 | local _min_0 = #_list_0 + -1 + 1 | ||
1216 | for _index_0 = _min_0, 1, -1 do | ||
1217 | local item = _list_0[_index_0] | ||
1218 | _accum_0[_len_0] = item | ||
1219 | _len_0 = _len_0 + 1 | ||
1220 | end | ||
1221 | reverse_slice = _accum_0 | ||
1222 | local sub_list | ||
1223 | local _accum_0 = { } | ||
1224 | local _len_0 = 1 | ||
1225 | local _list_0 = items | ||
1226 | for _index_0 = 2, 4 do | ||
1227 | local _item_0 = _list_0[_index_0] | ||
1228 | _accum_0[_len_0] = _item_0 | ||
1229 | _len_0 = _len_0 + 1 | ||
1230 | end | ||
1231 | sub_list = _accum_0 | ||
1000 | for i = 10, 20 do | 1232 | for i = 10, 20 do |
1001 | print(i) | 1233 | print(i) |
1002 | end | 1234 | end |
@@ -1007,8 +1239,7 @@ for key, value in pairs(object) do | |||
1007 | print(key, value) | 1239 | print(key, value) |
1008 | end | 1240 | end |
1009 | local _list_0 = items | 1241 | local _list_0 = items |
1010 | local _max_0 = 4 | 1242 | for _index_0 = 2, 4 do |
1011 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
1012 | local item = _list_0[_index_0] | 1243 | local item = _list_0[_index_0] |
1013 | print(item) | 1244 | print(item) |
1014 | end | 1245 | end |
@@ -1026,12 +1257,24 @@ local _len_0 = 1 | |||
1026 | for i = 1, 20 do | 1257 | for i = 1, 20 do |
1027 | if i % 2 == 0 then | 1258 | if i % 2 == 0 then |
1028 | _accum_0[_len_0] = i * 2 | 1259 | _accum_0[_len_0] = i * 2 |
1260 | _len_0 = _len_0 + 1 | ||
1029 | else | 1261 | else |
1030 | _accum_0[_len_0] = i | 1262 | _accum_0[_len_0] = i |
1263 | _len_0 = _len_0 + 1 | ||
1031 | end | 1264 | end |
1032 | _len_0 = _len_0 + 1 | ||
1033 | end | 1265 | end |
1034 | doubled_evens = _accum_0 | 1266 | doubled_evens = _accum_0 |
1267 | local first_large | ||
1268 | local _accum_0 | ||
1269 | local _list_0 = numbers | ||
1270 | for _index_0 = 1, #_list_0 do | ||
1271 | local n = _list_0[_index_0] | ||
1272 | if n > 10 then | ||
1273 | _accum_0 = n | ||
1274 | break | ||
1275 | end | ||
1276 | end | ||
1277 | first_large = _accum_0 | ||
1035 | local func_a | 1278 | local func_a |
1036 | func_a = function() | 1279 | func_a = function() |
1037 | for i = 1, 10 do | 1280 | for i = 1, 10 do |
@@ -1180,7 +1423,7 @@ if "Robert" == name then | |||
1180 | elseif "Dan" == name or "Daniel" == name then | 1423 | elseif "Dan" == name or "Daniel" == name then |
1181 | print("Your name, it's Dan") | 1424 | print("Your name, it's Dan") |
1182 | else | 1425 | else |
1183 | print("I don't know about your name") | 1426 | print("I don't know about you with name " .. tostring(name)) |
1184 | end | 1427 | end |
1185 | local b = 1 | 1428 | local b = 1 |
1186 | local next_number | 1429 | local next_number |
@@ -1280,6 +1523,192 @@ if _tab_0 then | |||
1280 | end | 1523 | end |
1281 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 1524 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
1282 | end | 1525 | end |
1526 | local _exp_0 = tb | ||
1527 | local _type_0 = type(_exp_0) | ||
1528 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1529 | local _match_0 = false | ||
1530 | if _tab_0 then | ||
1531 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
1532 | _match_0 = true | ||
1533 | print("1, 2, 3") | ||
1534 | end | ||
1535 | end | ||
1536 | if not _match_0 then | ||
1537 | local _match_1 = false | ||
1538 | if _tab_0 then | ||
1539 | local b = _exp_0[2] | ||
1540 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
1541 | _match_1 = true | ||
1542 | print("1, " .. tostring(b) .. ", 3") | ||
1543 | end | ||
1544 | end | ||
1545 | if not _match_1 then | ||
1546 | if _tab_0 then | ||
1547 | local b = _exp_0[3] | ||
1548 | if b == nil then | ||
1549 | b = 3 | ||
1550 | end | ||
1551 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
1552 | print("1, 2, " .. tostring(b)) | ||
1553 | end | ||
1554 | end | ||
1555 | end | ||
1556 | end | ||
1557 | local _exp_0 = tb | ||
1558 | local _type_0 = type(_exp_0) | ||
1559 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1560 | local _match_0 = false | ||
1561 | if _tab_0 then | ||
1562 | local result = _exp_0.result | ||
1563 | if true == _exp_0.success and result ~= nil then | ||
1564 | _match_0 = true | ||
1565 | print("success", result) | ||
1566 | end | ||
1567 | end | ||
1568 | if not _match_0 then | ||
1569 | local _match_1 = false | ||
1570 | if _tab_0 then | ||
1571 | if false == _exp_0.success then | ||
1572 | _match_1 = true | ||
1573 | print("failed", result) | ||
1574 | end | ||
1575 | end | ||
1576 | if not _match_1 then | ||
1577 | print("invalid") | ||
1578 | end | ||
1579 | end | ||
1580 | local _exp_0 = tb | ||
1581 | local _type_0 = type(_exp_0) | ||
1582 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1583 | local _match_0 = false | ||
1584 | if _tab_0 then | ||
1585 | local content | ||
1586 | do | ||
1587 | local _obj_0 = _exp_0.data | ||
1588 | local _type_1 = type(_obj_0) | ||
1589 | if "table" == _type_1 or "userdata" == _type_1 then | ||
1590 | content = _obj_0.content | ||
1591 | end | ||
1592 | end | ||
1593 | local _val_0 | ||
1594 | do | ||
1595 | local _obj_0 = _exp_0.data | ||
1596 | if _obj_0 ~= nil then | ||
1597 | _val_0 = _obj_0.type | ||
1598 | end | ||
1599 | end | ||
1600 | if "success" == _val_0 and content ~= nil then | ||
1601 | _match_0 = true | ||
1602 | print("success", content) | ||
1603 | end | ||
1604 | end | ||
1605 | if not _match_0 then | ||
1606 | local _match_1 = false | ||
1607 | if _tab_0 then | ||
1608 | local content | ||
1609 | do | ||
1610 | local _obj_0 = _exp_0.data | ||
1611 | local _type_1 = type(_obj_0) | ||
1612 | if "table" == _type_1 or "userdata" == _type_1 then | ||
1613 | content = _obj_0.content | ||
1614 | end | ||
1615 | end | ||
1616 | local _val_0 | ||
1617 | do | ||
1618 | local _obj_0 = _exp_0.data | ||
1619 | if _obj_0 ~= nil then | ||
1620 | _val_0 = _obj_0.type | ||
1621 | end | ||
1622 | end | ||
1623 | if "error" == _val_0 and content ~= nil then | ||
1624 | _match_1 = true | ||
1625 | print("failed", content) | ||
1626 | end | ||
1627 | end | ||
1628 | if not _match_1 then | ||
1629 | print("invalid") | ||
1630 | end | ||
1631 | end | ||
1632 | local _exp_0 = tb | ||
1633 | local _type_0 = type(_exp_0) | ||
1634 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1635 | if _tab_0 then | ||
1636 | local fourth = _exp_0[4] | ||
1637 | local _val_0 | ||
1638 | do | ||
1639 | local _obj_0 = _exp_0[1] | ||
1640 | if _obj_0 ~= nil then | ||
1641 | _val_0 = _obj_0.a | ||
1642 | end | ||
1643 | end | ||
1644 | local _val_1 | ||
1645 | do | ||
1646 | local _obj_0 = _exp_0[1] | ||
1647 | if _obj_0 ~= nil then | ||
1648 | _val_1 = _obj_0.b | ||
1649 | end | ||
1650 | end | ||
1651 | local _val_2 | ||
1652 | do | ||
1653 | local _obj_0 = _exp_0[2] | ||
1654 | if _obj_0 ~= nil then | ||
1655 | _val_2 = _obj_0.a | ||
1656 | end | ||
1657 | end | ||
1658 | local _val_3 | ||
1659 | do | ||
1660 | local _obj_0 = _exp_0[2] | ||
1661 | if _obj_0 ~= nil then | ||
1662 | _val_3 = _obj_0.b | ||
1663 | end | ||
1664 | end | ||
1665 | local _val_4 | ||
1666 | do | ||
1667 | local _obj_0 = _exp_0[3] | ||
1668 | if _obj_0 ~= nil then | ||
1669 | _val_4 = _obj_0.a | ||
1670 | end | ||
1671 | end | ||
1672 | local _val_5 | ||
1673 | do | ||
1674 | local _obj_0 = _exp_0[3] | ||
1675 | if _obj_0 ~= nil then | ||
1676 | _val_5 = _obj_0.b | ||
1677 | end | ||
1678 | end | ||
1679 | 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 | ||
1680 | print("matched", fourth) | ||
1681 | end | ||
1682 | end | ||
1683 | local segments = { | ||
1684 | "admin", | ||
1685 | "users", | ||
1686 | "logs", | ||
1687 | "view" | ||
1688 | } | ||
1689 | local _type_0 = type(segments) | ||
1690 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1691 | if _tab_0 then | ||
1692 | local groups | ||
1693 | do | ||
1694 | local _accum_0 = { } | ||
1695 | local _len_0 = 1 | ||
1696 | local _max_0 = #segments + -3 + 1 | ||
1697 | for _index_0 = 1, _max_0 do | ||
1698 | local _item_0 = segments[_index_0] | ||
1699 | _accum_0[_len_0] = _item_0 | ||
1700 | _len_0 = _len_0 + 1 | ||
1701 | end | ||
1702 | groups = _accum_0 | ||
1703 | end | ||
1704 | local resource = segments[#segments - 1] | ||
1705 | local action = segments[#segments] | ||
1706 | if resource ~= nil and action ~= nil then | ||
1707 | print("Group:", groups) | ||
1708 | print("Resource:", resource) | ||
1709 | print("Action:", action) | ||
1710 | end | ||
1711 | end | ||
1283 | local Inventory | 1712 | local Inventory |
1284 | local _class_0 | 1713 | local _class_0 |
1285 | local _base_0 = { | 1714 | local _base_0 = { |
@@ -1936,6 +2365,10 @@ do | |||
1936 | _with_1["key-name"] = value | 2365 | _with_1["key-name"] = value |
1937 | end | 2366 | end |
1938 | _with_0[#_with_0 + 1] = "abc" | 2367 | _with_0[#_with_0 + 1] = "abc" |
2368 | local _with_0 = obj | ||
2369 | if _with_0 ~= nil then | ||
2370 | print(obj.name) | ||
2371 | end | ||
1939 | do | 2372 | do |
1940 | local var = "hello" | 2373 | local var = "hello" |
1941 | print(var) | 2374 | print(var) |
@@ -2026,6 +2459,38 @@ local inventory = { | |||
2026 | } | 2459 | } |
2027 | } | 2460 | } |
2028 | } | 2461 | } |
2462 | local map | ||
2463 | map = function(arr, action) | ||
2464 | local _accum_0 = { } | ||
2465 | local _len_0 = 1 | ||
2466 | for _index_0 = 1, #arr do | ||
2467 | local item = arr[_index_0] | ||
2468 | _accum_0[_len_0] = action(item) | ||
2469 | _len_0 = _len_0 + 1 | ||
2470 | end | ||
2471 | return _accum_0 | ||
2472 | end | ||
2473 | local filter | ||
2474 | filter = function(arr, cond) | ||
2475 | local _accum_0 = { } | ||
2476 | local _len_0 = 1 | ||
2477 | for _index_0 = 1, #arr do | ||
2478 | local item = arr[_index_0] | ||
2479 | if cond(item) then | ||
2480 | _accum_0[_len_0] = item | ||
2481 | _len_0 = _len_0 + 1 | ||
2482 | end | ||
2483 | end | ||
2484 | return _accum_0 | ||
2485 | end | ||
2486 | local reduce | ||
2487 | reduce = function(arr, init, action) | ||
2488 | for _index_0 = 1, #arr do | ||
2489 | local item = arr[_index_0] | ||
2490 | init = action(init, item) | ||
2491 | end | ||
2492 | return init | ||
2493 | end | ||
2029 | print(reduce(filter(map({ | 2494 | print(reduce(filter(map({ |
2030 | 1, | 2495 | 1, |
2031 | 2, | 2496 | 2, |
@@ -2083,6 +2548,12 @@ end | |||
2083 | print("yuescript") | 2548 | print("yuescript") |
2084 | print(3) | 2549 | print(3) |
2085 | print("Valid enum type:", "Static") | 2550 | print("Valid enum type:", "Static") |
2551 | do | ||
2552 | print(123, "hello") | ||
2553 | end | ||
2554 | do | ||
2555 | print(123, "hello") | ||
2556 | end | ||
2086 | if tb ~= nil then | 2557 | if tb ~= nil then |
2087 | tb:func() | 2558 | tb:func() |
2088 | end | 2559 | end |
@@ -2183,6 +2654,16 @@ for _key_0, _value_0 in pairs(b) do | |||
2183 | end | 2654 | end |
2184 | end | 2655 | end |
2185 | merge = _tab_0 | 2656 | merge = _tab_0 |
2657 | local last | ||
2658 | do | ||
2659 | local _item_0 = data.items | ||
2660 | last = _item_0[#_item_0] | ||
2661 | end | ||
2662 | local second_last | ||
2663 | do | ||
2664 | local _item_0 = data.items | ||
2665 | second_last = _item_0[#_item_0 - 1] | ||
2666 | end | ||
2186 | local mt = { } | 2667 | local mt = { } |
2187 | local add | 2668 | local add |
2188 | add = function(self, right) | 2669 | add = function(self, right) |
@@ -2313,6 +2794,14 @@ func({ | |||
2313 | 2, | 2794 | 2, |
2314 | 3 | 2795 | 3 |
2315 | }) | 2796 | }) |
2797 | local f | ||
2798 | f = function() | ||
2799 | return { | ||
2800 | 1, | ||
2801 | 2, | ||
2802 | 3 | ||
2803 | } | ||
2804 | end | ||
2316 | local tb = { | 2805 | local tb = { |
2317 | name = "abc", | 2806 | name = "abc", |
2318 | values = { | 2807 | values = { |
@@ -2553,6 +3042,59 @@ end | |||
2553 | local two, four | 3042 | local two, four |
2554 | local _obj_0 = items | 3043 | local _obj_0 = items |
2555 | two, four = _obj_0[2], _obj_0[4] | 3044 | two, four = _obj_0[2], _obj_0[4] |
3045 | local orders = { | ||
3046 | "first", | ||
3047 | "second", | ||
3048 | "third", | ||
3049 | "fourth", | ||
3050 | "last" | ||
3051 | } | ||
3052 | local first, bulk, last = orders[1], (function() | ||
3053 | local _accum_0 = { } | ||
3054 | local _len_0 = 1 | ||
3055 | local _max_0 = #orders + -2 + 1 | ||
3056 | for _index_0 = 2, _max_0 do | ||
3057 | local _item_0 = orders[_index_0] | ||
3058 | _accum_0[_len_0] = _item_0 | ||
3059 | _len_0 = _len_0 + 1 | ||
3060 | end | ||
3061 | return _accum_0 | ||
3062 | end)(), orders[#orders] | ||
3063 | print(first) | ||
3064 | print(bulk) | ||
3065 | print(last) | ||
3066 | local first, rest | ||
3067 | do | ||
3068 | local _obj_0 = orders | ||
3069 | first, rest = _obj_0[1], (function() | ||
3070 | local _accum_0 = { } | ||
3071 | local _len_0 = 1 | ||
3072 | local _max_0 = #_obj_0 | ||
3073 | for _index_0 = 2, _max_0 do | ||
3074 | local _item_0 = _obj_0[_index_0] | ||
3075 | _accum_0[_len_0] = _item_0 | ||
3076 | _len_0 = _len_0 + 1 | ||
3077 | end | ||
3078 | return _accum_0 | ||
3079 | end)() | ||
3080 | end | ||
3081 | local start, last | ||
3082 | do | ||
3083 | local _obj_0 = orders | ||
3084 | start, last = (function() | ||
3085 | local _accum_0 = { } | ||
3086 | local _len_0 = 1 | ||
3087 | local _max_0 = #_obj_0 + -2 + 1 | ||
3088 | for _index_0 = 1, _max_0 do | ||
3089 | local _item_0 = _obj_0[_index_0] | ||
3090 | _accum_0[_len_0] = _item_0 | ||
3091 | _len_0 = _len_0 + 1 | ||
3092 | end | ||
3093 | return _accum_0 | ||
3094 | end)(), _obj_0[#_obj_0] | ||
3095 | end | ||
3096 | local _obj_0 = orders | ||
3097 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
2556 | local tuples = { | 3098 | local tuples = { |
2557 | { | 3099 | { |
2558 | "hello", | 3100 | "hello", |
@@ -2654,6 +3196,56 @@ end) | |||
2654 | if success then | 3196 | if success then |
2655 | print(result) | 3197 | print(result) |
2656 | end | 3198 | end |
3199 | local a, b, c | ||
3200 | do | ||
3201 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
3202 | return func() | ||
3203 | end) | ||
3204 | if _ok_0 then | ||
3205 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
3206 | end | ||
3207 | end | ||
3208 | do | ||
3209 | local _exp_0 = ((function() | ||
3210 | return (function(_arg_0, ...) | ||
3211 | local _ok_0 = _arg_0 | ||
3212 | if _ok_0 then | ||
3213 | return ... | ||
3214 | end | ||
3215 | end)(pcall(function() | ||
3216 | return func() | ||
3217 | end)) | ||
3218 | end)()) | ||
3219 | if _exp_0 ~= nil then | ||
3220 | a = _exp_0 | ||
3221 | else | ||
3222 | a = "default" | ||
3223 | end | ||
3224 | end | ||
3225 | f((function() | ||
3226 | return (function(_arg_0, ...) | ||
3227 | local _ok_0 = _arg_0 | ||
3228 | if _ok_0 then | ||
3229 | return ... | ||
3230 | end | ||
3231 | end)(pcall(function() | ||
3232 | return func() | ||
3233 | end)) | ||
3234 | end)()) | ||
3235 | f((function() | ||
3236 | return (function(_arg_0, ...) | ||
3237 | local _ok_0 = _arg_0 | ||
3238 | if _ok_0 then | ||
3239 | return ... | ||
3240 | end | ||
3241 | end)(xpcall(function() | ||
3242 | print(123) | ||
3243 | return func() | ||
3244 | end, function(e) | ||
3245 | print(e) | ||
3246 | return e | ||
3247 | end)) | ||
3248 | end)()) | ||
2657 | local a <const> = 123 | 3249 | local a <const> = 123 |
2658 | local _ <close> = setmetatable({ }, { | 3250 | local _ <close> = setmetatable({ }, { |
2659 | __close = function() | 3251 | __close = function() |
@@ -2663,10 +3255,19 @@ local _ <close> = setmetatable({ }, { | |||
2663 | local a, b, c, d | 3255 | local a, b, c, d |
2664 | local _obj_0 = tb | 3256 | local _obj_0 = tb |
2665 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 3257 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
3258 | Constant = 123 | ||
2666 | local some_string = "Here is a string\n that has a line break in it." | 3259 | local some_string = "Here is a string\n that has a line break in it." |
2667 | print("I am " .. tostring(math.random() * 100) .. "% sure.") | 3260 | print("I am " .. tostring(math.random() * 100) .. "% sure.") |
2668 | local integer = 1000000 | 3261 | local integer = 1000000 |
2669 | local hex = 0xEFBBBF | 3262 | local hex = 0xEFBBBF |
3263 | local binary = 19 | ||
3264 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
3265 | local fn | ||
3266 | fn = function() | ||
3267 | local str = "foo:\n bar: baz" | ||
3268 | return str | ||
3269 | end | ||
3270 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
2670 | local my_function | 3271 | local my_function |
2671 | my_function = function() end | 3272 | my_function = function() end |
2672 | my_function() | 3273 | my_function() |
@@ -2761,6 +3362,66 @@ if func(1, 2, 3, "hello", "world") then | |||
2761 | print("hello") | 3362 | print("hello") |
2762 | print("I am inside if") | 3363 | print("I am inside if") |
2763 | end | 3364 | end |
3365 | local f1 | ||
3366 | f1 = function(_arg_0) | ||
3367 | local a, b, c | ||
3368 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
3369 | return print(a, b, c) | ||
3370 | end | ||
3371 | f1({ | ||
3372 | a = 1, | ||
3373 | b = "2", | ||
3374 | c = { } | ||
3375 | }) | ||
3376 | local f2 | ||
3377 | f2 = function(_arg_0, c) | ||
3378 | local a1, b | ||
3379 | a1, b = _arg_0.a, _arg_0.b | ||
3380 | if a1 == nil then | ||
3381 | a1 = 123 | ||
3382 | end | ||
3383 | if b == nil then | ||
3384 | b = 'abc' | ||
3385 | end | ||
3386 | if c == nil then | ||
3387 | c = { } | ||
3388 | end | ||
3389 | end | ||
3390 | print(a1, b, c) | ||
3391 | local arg1 = { | ||
3392 | a = 0 | ||
3393 | } | ||
3394 | f2(arg1, arg2) | ||
3395 | local findFirstEven | ||
3396 | findFirstEven = function(list) | ||
3397 | for _index_0 = 1, #list do | ||
3398 | local item = list[_index_0] | ||
3399 | if type(item) == "table" then | ||
3400 | for _index_1 = 1, #item do | ||
3401 | local sub = item[_index_1] | ||
3402 | if sub % 2 == 0 then | ||
3403 | return sub | ||
3404 | end | ||
3405 | end | ||
3406 | end | ||
3407 | end | ||
3408 | return nil | ||
3409 | end | ||
3410 | local findFirstEven | ||
3411 | findFirstEven = function(list) | ||
3412 | for _index_0 = 1, #list do | ||
3413 | local item = list[_index_0] | ||
3414 | if type(item) == "table" then | ||
3415 | for _index_1 = 1, #item do | ||
3416 | local sub = item[_index_1] | ||
3417 | if sub % 2 == 0 then | ||
3418 | return sub | ||
3419 | end | ||
3420 | end | ||
3421 | end | ||
3422 | end | ||
3423 | return nil | ||
3424 | end | ||
2764 | f(function() | 3425 | f(function() |
2765 | return print("hello") | 3426 | return print("hello") |
2766 | end) | 3427 | end) |
@@ -2976,8 +3637,7 @@ local slice | |||
2976 | local _accum_0 = { } | 3637 | local _accum_0 = { } |
2977 | local _len_0 = 1 | 3638 | local _len_0 = 1 |
2978 | local _list_0 = items | 3639 | local _list_0 = items |
2979 | local _max_0 = 5 | 3640 | for _index_0 = 1, 5 do |
2980 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
2981 | local item = _list_0[_index_0] | 3641 | local item = _list_0[_index_0] |
2982 | _accum_0[_len_0] = item | 3642 | _accum_0[_len_0] = item |
2983 | _len_0 = _len_0 + 1 | 3643 | _len_0 = _len_0 + 1 |
@@ -2987,7 +3647,8 @@ local slice | |||
2987 | local _accum_0 = { } | 3647 | local _accum_0 = { } |
2988 | local _len_0 = 1 | 3648 | local _len_0 = 1 |
2989 | local _list_0 = items | 3649 | local _list_0 = items |
2990 | for _index_0 = 2, #_list_0 do | 3650 | local _max_0 = #_list_0 |
3651 | for _index_0 = 2, _max_0 do | ||
2991 | local item = _list_0[_index_0] | 3652 | local item = _list_0[_index_0] |
2992 | _accum_0[_len_0] = item | 3653 | _accum_0[_len_0] = item |
2993 | _len_0 = _len_0 + 1 | 3654 | _len_0 = _len_0 + 1 |
@@ -2997,12 +3658,46 @@ local slice | |||
2997 | local _accum_0 = { } | 3658 | local _accum_0 = { } |
2998 | local _len_0 = 1 | 3659 | local _len_0 = 1 |
2999 | local _list_0 = items | 3660 | local _list_0 = items |
3000 | for _index_0 = 1, #_list_0, 2 do | 3661 | local _max_0 = #_list_0 |
3662 | for _index_0 = 1, _max_0, 2 do | ||
3001 | local item = _list_0[_index_0] | 3663 | local item = _list_0[_index_0] |
3002 | _accum_0[_len_0] = item | 3664 | _accum_0[_len_0] = item |
3003 | _len_0 = _len_0 + 1 | 3665 | _len_0 = _len_0 + 1 |
3004 | end | 3666 | end |
3005 | slice = _accum_0 | 3667 | slice = _accum_0 |
3668 | local slice | ||
3669 | local _accum_0 = { } | ||
3670 | local _len_0 = 1 | ||
3671 | local _list_0 = items | ||
3672 | local _min_0 = #_list_0 + -4 + 1 | ||
3673 | local _max_0 = #_list_0 + -1 + 1 | ||
3674 | for _index_0 = _min_0, _max_0 do | ||
3675 | local item = _list_0[_index_0] | ||
3676 | _accum_0[_len_0] = item | ||
3677 | _len_0 = _len_0 + 1 | ||
3678 | end | ||
3679 | slice = _accum_0 | ||
3680 | local reverse_slice | ||
3681 | local _accum_0 = { } | ||
3682 | local _len_0 = 1 | ||
3683 | local _list_0 = items | ||
3684 | local _min_0 = #_list_0 + -1 + 1 | ||
3685 | for _index_0 = _min_0, 1, -1 do | ||
3686 | local item = _list_0[_index_0] | ||
3687 | _accum_0[_len_0] = item | ||
3688 | _len_0 = _len_0 + 1 | ||
3689 | end | ||
3690 | reverse_slice = _accum_0 | ||
3691 | local sub_list | ||
3692 | local _accum_0 = { } | ||
3693 | local _len_0 = 1 | ||
3694 | local _list_0 = items | ||
3695 | for _index_0 = 2, 4 do | ||
3696 | local _item_0 = _list_0[_index_0] | ||
3697 | _accum_0[_len_0] = _item_0 | ||
3698 | _len_0 = _len_0 + 1 | ||
3699 | end | ||
3700 | sub_list = _accum_0 | ||
3006 | for i = 10, 20 do | 3701 | for i = 10, 20 do |
3007 | print(i) | 3702 | print(i) |
3008 | end | 3703 | end |
@@ -3013,8 +3708,7 @@ for key, value in pairs(object) do | |||
3013 | print(key, value) | 3708 | print(key, value) |
3014 | end | 3709 | end |
3015 | local _list_0 = items | 3710 | local _list_0 = items |
3016 | local _max_0 = 4 | 3711 | for _index_0 = 2, 4 do |
3017 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
3018 | local item = _list_0[_index_0] | 3712 | local item = _list_0[_index_0] |
3019 | print(item) | 3713 | print(item) |
3020 | end | 3714 | end |
@@ -3032,12 +3726,24 @@ local _len_0 = 1 | |||
3032 | for i = 1, 20 do | 3726 | for i = 1, 20 do |
3033 | if i % 2 == 0 then | 3727 | if i % 2 == 0 then |
3034 | _accum_0[_len_0] = i * 2 | 3728 | _accum_0[_len_0] = i * 2 |
3729 | _len_0 = _len_0 + 1 | ||
3035 | else | 3730 | else |
3036 | _accum_0[_len_0] = i | 3731 | _accum_0[_len_0] = i |
3732 | _len_0 = _len_0 + 1 | ||
3037 | end | 3733 | end |
3038 | _len_0 = _len_0 + 1 | ||
3039 | end | 3734 | end |
3040 | doubled_evens = _accum_0 | 3735 | doubled_evens = _accum_0 |
3736 | local first_large | ||
3737 | local _accum_0 | ||
3738 | local _list_0 = numbers | ||
3739 | for _index_0 = 1, #_list_0 do | ||
3740 | local n = _list_0[_index_0] | ||
3741 | if n > 10 then | ||
3742 | _accum_0 = n | ||
3743 | break | ||
3744 | end | ||
3745 | end | ||
3746 | first_large = _accum_0 | ||
3041 | local func_a | 3747 | local func_a |
3042 | func_a = function() | 3748 | func_a = function() |
3043 | for i = 1, 10 do | 3749 | for i = 1, 10 do |
@@ -3186,7 +3892,7 @@ if "Robert" == name then | |||
3186 | elseif "Dan" == name or "Daniel" == name then | 3892 | elseif "Dan" == name or "Daniel" == name then |
3187 | print("Your name, it's Dan") | 3893 | print("Your name, it's Dan") |
3188 | else | 3894 | else |
3189 | print("I don't know about your name") | 3895 | print("I don't know about you with name " .. tostring(name)) |
3190 | end | 3896 | end |
3191 | local b = 1 | 3897 | local b = 1 |
3192 | local next_number | 3898 | local next_number |
@@ -3286,6 +3992,192 @@ if _tab_0 then | |||
3286 | end | 3992 | end |
3287 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 3993 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
3288 | end | 3994 | end |
3995 | local _exp_0 = tb | ||
3996 | local _type_0 = type(_exp_0) | ||
3997 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
3998 | local _match_0 = false | ||
3999 | if _tab_0 then | ||
4000 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
4001 | _match_0 = true | ||
4002 | print("1, 2, 3") | ||
4003 | end | ||
4004 | end | ||
4005 | if not _match_0 then | ||
4006 | local _match_1 = false | ||
4007 | if _tab_0 then | ||
4008 | local b = _exp_0[2] | ||
4009 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
4010 | _match_1 = true | ||
4011 | print("1, " .. tostring(b) .. ", 3") | ||
4012 | end | ||
4013 | end | ||
4014 | if not _match_1 then | ||
4015 | if _tab_0 then | ||
4016 | local b = _exp_0[3] | ||
4017 | if b == nil then | ||
4018 | b = 3 | ||
4019 | end | ||
4020 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
4021 | print("1, 2, " .. tostring(b)) | ||
4022 | end | ||
4023 | end | ||
4024 | end | ||
4025 | end | ||
4026 | local _exp_0 = tb | ||
4027 | local _type_0 = type(_exp_0) | ||
4028 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4029 | local _match_0 = false | ||
4030 | if _tab_0 then | ||
4031 | local result = _exp_0.result | ||
4032 | if true == _exp_0.success and result ~= nil then | ||
4033 | _match_0 = true | ||
4034 | print("success", result) | ||
4035 | end | ||
4036 | end | ||
4037 | if not _match_0 then | ||
4038 | local _match_1 = false | ||
4039 | if _tab_0 then | ||
4040 | if false == _exp_0.success then | ||
4041 | _match_1 = true | ||
4042 | print("failed", result) | ||
4043 | end | ||
4044 | end | ||
4045 | if not _match_1 then | ||
4046 | print("invalid") | ||
4047 | end | ||
4048 | end | ||
4049 | local _exp_0 = tb | ||
4050 | local _type_0 = type(_exp_0) | ||
4051 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4052 | local _match_0 = false | ||
4053 | if _tab_0 then | ||
4054 | local content | ||
4055 | do | ||
4056 | local _obj_0 = _exp_0.data | ||
4057 | local _type_1 = type(_obj_0) | ||
4058 | if "table" == _type_1 or "userdata" == _type_1 then | ||
4059 | content = _obj_0.content | ||
4060 | end | ||
4061 | end | ||
4062 | local _val_0 | ||
4063 | do | ||
4064 | local _obj_0 = _exp_0.data | ||
4065 | if _obj_0 ~= nil then | ||
4066 | _val_0 = _obj_0.type | ||
4067 | end | ||
4068 | end | ||
4069 | if "success" == _val_0 and content ~= nil then | ||
4070 | _match_0 = true | ||
4071 | print("success", content) | ||
4072 | end | ||
4073 | end | ||
4074 | if not _match_0 then | ||
4075 | local _match_1 = false | ||
4076 | if _tab_0 then | ||
4077 | local content | ||
4078 | do | ||
4079 | local _obj_0 = _exp_0.data | ||
4080 | local _type_1 = type(_obj_0) | ||
4081 | if "table" == _type_1 or "userdata" == _type_1 then | ||
4082 | content = _obj_0.content | ||
4083 | end | ||
4084 | end | ||
4085 | local _val_0 | ||
4086 | do | ||
4087 | local _obj_0 = _exp_0.data | ||
4088 | if _obj_0 ~= nil then | ||
4089 | _val_0 = _obj_0.type | ||
4090 | end | ||
4091 | end | ||
4092 | if "error" == _val_0 and content ~= nil then | ||
4093 | _match_1 = true | ||
4094 | print("failed", content) | ||
4095 | end | ||
4096 | end | ||
4097 | if not _match_1 then | ||
4098 | print("invalid") | ||
4099 | end | ||
4100 | end | ||
4101 | local _exp_0 = tb | ||
4102 | local _type_0 = type(_exp_0) | ||
4103 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4104 | if _tab_0 then | ||
4105 | local fourth = _exp_0[4] | ||
4106 | local _val_0 | ||
4107 | do | ||
4108 | local _obj_0 = _exp_0[1] | ||
4109 | if _obj_0 ~= nil then | ||
4110 | _val_0 = _obj_0.a | ||
4111 | end | ||
4112 | end | ||
4113 | local _val_1 | ||
4114 | do | ||
4115 | local _obj_0 = _exp_0[1] | ||
4116 | if _obj_0 ~= nil then | ||
4117 | _val_1 = _obj_0.b | ||
4118 | end | ||
4119 | end | ||
4120 | local _val_2 | ||
4121 | do | ||
4122 | local _obj_0 = _exp_0[2] | ||
4123 | if _obj_0 ~= nil then | ||
4124 | _val_2 = _obj_0.a | ||
4125 | end | ||
4126 | end | ||
4127 | local _val_3 | ||
4128 | do | ||
4129 | local _obj_0 = _exp_0[2] | ||
4130 | if _obj_0 ~= nil then | ||
4131 | _val_3 = _obj_0.b | ||
4132 | end | ||
4133 | end | ||
4134 | local _val_4 | ||
4135 | do | ||
4136 | local _obj_0 = _exp_0[3] | ||
4137 | if _obj_0 ~= nil then | ||
4138 | _val_4 = _obj_0.a | ||
4139 | end | ||
4140 | end | ||
4141 | local _val_5 | ||
4142 | do | ||
4143 | local _obj_0 = _exp_0[3] | ||
4144 | if _obj_0 ~= nil then | ||
4145 | _val_5 = _obj_0.b | ||
4146 | end | ||
4147 | end | ||
4148 | 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 | ||
4149 | print("matched", fourth) | ||
4150 | end | ||
4151 | end | ||
4152 | local segments = { | ||
4153 | "admin", | ||
4154 | "users", | ||
4155 | "logs", | ||
4156 | "view" | ||
4157 | } | ||
4158 | local _type_0 = type(segments) | ||
4159 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4160 | if _tab_0 then | ||
4161 | local groups | ||
4162 | do | ||
4163 | local _accum_0 = { } | ||
4164 | local _len_0 = 1 | ||
4165 | local _max_0 = #segments + -3 + 1 | ||
4166 | for _index_0 = 1, _max_0 do | ||
4167 | local _item_0 = segments[_index_0] | ||
4168 | _accum_0[_len_0] = _item_0 | ||
4169 | _len_0 = _len_0 + 1 | ||
4170 | end | ||
4171 | groups = _accum_0 | ||
4172 | end | ||
4173 | local resource = segments[#segments - 1] | ||
4174 | local action = segments[#segments] | ||
4175 | if resource ~= nil and action ~= nil then | ||
4176 | print("Group:", groups) | ||
4177 | print("Resource:", resource) | ||
4178 | print("Action:", action) | ||
4179 | end | ||
4180 | end | ||
3289 | local Inventory | 4181 | local Inventory |
3290 | local _class_0 | 4182 | local _class_0 |
3291 | local _base_0 = { | 4183 | local _base_0 = { |
@@ -3942,6 +4834,10 @@ do | |||
3942 | _with_1["key-name"] = value | 4834 | _with_1["key-name"] = value |
3943 | end | 4835 | end |
3944 | _with_0[#_with_0 + 1] = "abc" | 4836 | _with_0[#_with_0 + 1] = "abc" |
4837 | local _with_0 = obj | ||
4838 | if _with_0 ~= nil then | ||
4839 | print(obj.name) | ||
4840 | end | ||
3945 | do | 4841 | do |
3946 | local var = "hello" | 4842 | local var = "hello" |
3947 | print(var) | 4843 | print(var) |
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index acd41a0..de76829 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua | |||
@@ -20,6 +20,38 @@ local inventory = { | |||
20 | } | 20 | } |
21 | } | 21 | } |
22 | } | 22 | } |
23 | local map | ||
24 | map = function(arr, action) | ||
25 | local _accum_0 = { } | ||
26 | local _len_0 = 1 | ||
27 | for _index_0 = 1, #arr do | ||
28 | local item = arr[_index_0] | ||
29 | _accum_0[_len_0] = action(item) | ||
30 | _len_0 = _len_0 + 1 | ||
31 | end | ||
32 | return _accum_0 | ||
33 | end | ||
34 | local filter | ||
35 | filter = function(arr, cond) | ||
36 | local _accum_0 = { } | ||
37 | local _len_0 = 1 | ||
38 | for _index_0 = 1, #arr do | ||
39 | local item = arr[_index_0] | ||
40 | if cond(item) then | ||
41 | _accum_0[_len_0] = item | ||
42 | _len_0 = _len_0 + 1 | ||
43 | end | ||
44 | end | ||
45 | return _accum_0 | ||
46 | end | ||
47 | local reduce | ||
48 | reduce = function(arr, init, action) | ||
49 | for _index_0 = 1, #arr do | ||
50 | local item = arr[_index_0] | ||
51 | init = action(init, item) | ||
52 | end | ||
53 | return init | ||
54 | end | ||
23 | print(reduce(filter(map({ | 55 | print(reduce(filter(map({ |
24 | 1, | 56 | 1, |
25 | 2, | 57 | 2, |
@@ -77,6 +109,12 @@ end | |||
77 | print("yuescript") | 109 | print("yuescript") |
78 | print(3) | 110 | print(3) |
79 | print("有效的枚举类型:", "Static") | 111 | print("有效的枚举类型:", "Static") |
112 | do | ||
113 | print(123, "hello") | ||
114 | end | ||
115 | do | ||
116 | print(123, "hello") | ||
117 | end | ||
80 | if tb ~= nil then | 118 | if tb ~= nil then |
81 | tb:func() | 119 | tb:func() |
82 | end | 120 | end |
@@ -177,6 +215,16 @@ for _key_0, _value_0 in pairs(b) do | |||
177 | end | 215 | end |
178 | end | 216 | end |
179 | merge = _tab_0 | 217 | merge = _tab_0 |
218 | local last | ||
219 | do | ||
220 | local _item_0 = data.items | ||
221 | last = _item_0[#_item_0] | ||
222 | end | ||
223 | local second_last | ||
224 | do | ||
225 | local _item_0 = data.items | ||
226 | second_last = _item_0[#_item_0 - 1] | ||
227 | end | ||
180 | local mt = { } | 228 | local mt = { } |
181 | local add | 229 | local add |
182 | add = function(self, right) | 230 | add = function(self, right) |
@@ -307,6 +355,14 @@ func({ | |||
307 | 2, | 355 | 2, |
308 | 3 | 356 | 3 |
309 | }) | 357 | }) |
358 | local f | ||
359 | f = function() | ||
360 | return { | ||
361 | 1, | ||
362 | 2, | ||
363 | 3 | ||
364 | } | ||
365 | end | ||
310 | local tb = { | 366 | local tb = { |
311 | name = "abc", | 367 | name = "abc", |
312 | values = { | 368 | values = { |
@@ -547,6 +603,59 @@ end | |||
547 | local two, four | 603 | local two, four |
548 | local _obj_0 = items | 604 | local _obj_0 = items |
549 | two, four = _obj_0[2], _obj_0[4] | 605 | two, four = _obj_0[2], _obj_0[4] |
606 | local orders = { | ||
607 | "first", | ||
608 | "second", | ||
609 | "third", | ||
610 | "fourth", | ||
611 | "last" | ||
612 | } | ||
613 | local first, bulk, last = orders[1], (function() | ||
614 | local _accum_0 = { } | ||
615 | local _len_0 = 1 | ||
616 | local _max_0 = #orders + -2 + 1 | ||
617 | for _index_0 = 2, _max_0 do | ||
618 | local _item_0 = orders[_index_0] | ||
619 | _accum_0[_len_0] = _item_0 | ||
620 | _len_0 = _len_0 + 1 | ||
621 | end | ||
622 | return _accum_0 | ||
623 | end)(), orders[#orders] | ||
624 | print(first) | ||
625 | print(bulk) | ||
626 | print(last) | ||
627 | local first, rest | ||
628 | do | ||
629 | local _obj_0 = orders | ||
630 | first, rest = _obj_0[1], (function() | ||
631 | local _accum_0 = { } | ||
632 | local _len_0 = 1 | ||
633 | local _max_0 = #_obj_0 | ||
634 | for _index_0 = 2, _max_0 do | ||
635 | local _item_0 = _obj_0[_index_0] | ||
636 | _accum_0[_len_0] = _item_0 | ||
637 | _len_0 = _len_0 + 1 | ||
638 | end | ||
639 | return _accum_0 | ||
640 | end)() | ||
641 | end | ||
642 | local start, last | ||
643 | do | ||
644 | local _obj_0 = orders | ||
645 | start, last = (function() | ||
646 | local _accum_0 = { } | ||
647 | local _len_0 = 1 | ||
648 | local _max_0 = #_obj_0 + -2 + 1 | ||
649 | for _index_0 = 1, _max_0 do | ||
650 | local _item_0 = _obj_0[_index_0] | ||
651 | _accum_0[_len_0] = _item_0 | ||
652 | _len_0 = _len_0 + 1 | ||
653 | end | ||
654 | return _accum_0 | ||
655 | end)(), _obj_0[#_obj_0] | ||
656 | end | ||
657 | local _obj_0 = orders | ||
658 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
550 | local tuples = { | 659 | local tuples = { |
551 | { | 660 | { |
552 | "hello", | 661 | "hello", |
@@ -648,6 +757,56 @@ end) | |||
648 | if success then | 757 | if success then |
649 | print(result) | 758 | print(result) |
650 | end | 759 | end |
760 | local a, b, c | ||
761 | do | ||
762 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
763 | return func() | ||
764 | end) | ||
765 | if _ok_0 then | ||
766 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
767 | end | ||
768 | end | ||
769 | do | ||
770 | local _exp_0 = ((function() | ||
771 | return (function(_arg_0, ...) | ||
772 | local _ok_0 = _arg_0 | ||
773 | if _ok_0 then | ||
774 | return ... | ||
775 | end | ||
776 | end)(pcall(function() | ||
777 | return func() | ||
778 | end)) | ||
779 | end)()) | ||
780 | if _exp_0 ~= nil then | ||
781 | a = _exp_0 | ||
782 | else | ||
783 | a = "default" | ||
784 | end | ||
785 | end | ||
786 | f((function() | ||
787 | return (function(_arg_0, ...) | ||
788 | local _ok_0 = _arg_0 | ||
789 | if _ok_0 then | ||
790 | return ... | ||
791 | end | ||
792 | end)(pcall(function() | ||
793 | return func() | ||
794 | end)) | ||
795 | end)()) | ||
796 | f((function() | ||
797 | return (function(_arg_0, ...) | ||
798 | local _ok_0 = _arg_0 | ||
799 | if _ok_0 then | ||
800 | return ... | ||
801 | end | ||
802 | end)(xpcall(function() | ||
803 | print(123) | ||
804 | return func() | ||
805 | end, function(e) | ||
806 | print(e) | ||
807 | return e | ||
808 | end)) | ||
809 | end)()) | ||
651 | local a <const> = 123 | 810 | local a <const> = 123 |
652 | local _ <close> = setmetatable({ }, { | 811 | local _ <close> = setmetatable({ }, { |
653 | __close = function() | 812 | __close = function() |
@@ -657,10 +816,19 @@ local _ <close> = setmetatable({ }, { | |||
657 | local a, b, c, d | 816 | local a, b, c, d |
658 | local _obj_0 = tb | 817 | local _obj_0 = tb |
659 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 818 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
819 | Constant = 123 | ||
660 | local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" | 820 | local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" |
661 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") | 821 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") |
662 | local integer = 1000000 | 822 | local integer = 1000000 |
663 | local hex = 0xEFBBBF | 823 | local hex = 0xEFBBBF |
824 | local binary = 19 | ||
825 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
826 | local fn | ||
827 | fn = function() | ||
828 | local str = "foo:\n bar: baz" | ||
829 | return str | ||
830 | end | ||
831 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
664 | local my_function | 832 | local my_function |
665 | my_function = function() end | 833 | my_function = function() end |
666 | my_function() | 834 | my_function() |
@@ -749,6 +917,36 @@ if func(1, 2, 3, "ä½ å¥½", "世界") then | |||
749 | print("hello") | 917 | print("hello") |
750 | print("我在if内部") | 918 | print("我在if内部") |
751 | end | 919 | end |
920 | local f1 | ||
921 | f1 = function(_arg_0) | ||
922 | local a, b, c | ||
923 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
924 | return print(a, b, c) | ||
925 | end | ||
926 | f1({ | ||
927 | a = 1, | ||
928 | b = "2", | ||
929 | c = { } | ||
930 | }) | ||
931 | local f2 | ||
932 | f2 = function(_arg_0, c) | ||
933 | local a1, b | ||
934 | a1, b = _arg_0.a, _arg_0.b | ||
935 | if a1 == nil then | ||
936 | a1 = 123 | ||
937 | end | ||
938 | if b == nil then | ||
939 | b = 'abc' | ||
940 | end | ||
941 | if c == nil then | ||
942 | c = { } | ||
943 | end | ||
944 | return print(a1, b, c) | ||
945 | end | ||
946 | local arg1 = { | ||
947 | a = 0 | ||
948 | } | ||
949 | f2(arg1, arg2) | ||
752 | f(function() | 950 | f(function() |
753 | return print("hello") | 951 | return print("hello") |
754 | end) | 952 | end) |
@@ -964,8 +1162,7 @@ local slice | |||
964 | local _accum_0 = { } | 1162 | local _accum_0 = { } |
965 | local _len_0 = 1 | 1163 | local _len_0 = 1 |
966 | local _list_0 = items | 1164 | local _list_0 = items |
967 | local _max_0 = 5 | 1165 | for _index_0 = 1, 5 do |
968 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
969 | local item = _list_0[_index_0] | 1166 | local item = _list_0[_index_0] |
970 | _accum_0[_len_0] = item | 1167 | _accum_0[_len_0] = item |
971 | _len_0 = _len_0 + 1 | 1168 | _len_0 = _len_0 + 1 |
@@ -975,7 +1172,8 @@ local slice | |||
975 | local _accum_0 = { } | 1172 | local _accum_0 = { } |
976 | local _len_0 = 1 | 1173 | local _len_0 = 1 |
977 | local _list_0 = items | 1174 | local _list_0 = items |
978 | for _index_0 = 2, #_list_0 do | 1175 | local _max_0 = #_list_0 |
1176 | for _index_0 = 2, _max_0 do | ||
979 | local item = _list_0[_index_0] | 1177 | local item = _list_0[_index_0] |
980 | _accum_0[_len_0] = item | 1178 | _accum_0[_len_0] = item |
981 | _len_0 = _len_0 + 1 | 1179 | _len_0 = _len_0 + 1 |
@@ -985,12 +1183,46 @@ local slice | |||
985 | local _accum_0 = { } | 1183 | local _accum_0 = { } |
986 | local _len_0 = 1 | 1184 | local _len_0 = 1 |
987 | local _list_0 = items | 1185 | local _list_0 = items |
988 | for _index_0 = 1, #_list_0, 2 do | 1186 | local _max_0 = #_list_0 |
1187 | for _index_0 = 1, _max_0, 2 do | ||
989 | local item = _list_0[_index_0] | 1188 | local item = _list_0[_index_0] |
990 | _accum_0[_len_0] = item | 1189 | _accum_0[_len_0] = item |
991 | _len_0 = _len_0 + 1 | 1190 | _len_0 = _len_0 + 1 |
992 | end | 1191 | end |
993 | slice = _accum_0 | 1192 | slice = _accum_0 |
1193 | local slice | ||
1194 | local _accum_0 = { } | ||
1195 | local _len_0 = 1 | ||
1196 | local _list_0 = items | ||
1197 | local _min_0 = #_list_0 + -4 + 1 | ||
1198 | local _max_0 = #_list_0 + -1 + 1 | ||
1199 | for _index_0 = _min_0, _max_0 do | ||
1200 | local item = _list_0[_index_0] | ||
1201 | _accum_0[_len_0] = item | ||
1202 | _len_0 = _len_0 + 1 | ||
1203 | end | ||
1204 | slice = _accum_0 | ||
1205 | local reverse_slice | ||
1206 | local _accum_0 = { } | ||
1207 | local _len_0 = 1 | ||
1208 | local _list_0 = items | ||
1209 | local _min_0 = #_list_0 + -1 + 1 | ||
1210 | for _index_0 = _min_0, 1, -1 do | ||
1211 | local item = _list_0[_index_0] | ||
1212 | _accum_0[_len_0] = item | ||
1213 | _len_0 = _len_0 + 1 | ||
1214 | end | ||
1215 | reverse_slice = _accum_0 | ||
1216 | local sub_list | ||
1217 | local _accum_0 = { } | ||
1218 | local _len_0 = 1 | ||
1219 | local _list_0 = items | ||
1220 | for _index_0 = 2, 4 do | ||
1221 | local _item_0 = _list_0[_index_0] | ||
1222 | _accum_0[_len_0] = _item_0 | ||
1223 | _len_0 = _len_0 + 1 | ||
1224 | end | ||
1225 | sub_list = _accum_0 | ||
994 | for i = 10, 20 do | 1226 | for i = 10, 20 do |
995 | print(i) | 1227 | print(i) |
996 | end | 1228 | end |
@@ -1001,8 +1233,7 @@ for key, value in pairs(object) do | |||
1001 | print(key, value) | 1233 | print(key, value) |
1002 | end | 1234 | end |
1003 | local _list_0 = items | 1235 | local _list_0 = items |
1004 | local _max_0 = 4 | 1236 | for _index_0 = 2, 4 do |
1005 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
1006 | local item = _list_0[_index_0] | 1237 | local item = _list_0[_index_0] |
1007 | print(item) | 1238 | print(item) |
1008 | end | 1239 | end |
@@ -1020,12 +1251,24 @@ local _len_0 = 1 | |||
1020 | for i = 1, 20 do | 1251 | for i = 1, 20 do |
1021 | if i % 2 == 0 then | 1252 | if i % 2 == 0 then |
1022 | _accum_0[_len_0] = i * 2 | 1253 | _accum_0[_len_0] = i * 2 |
1254 | _len_0 = _len_0 + 1 | ||
1023 | else | 1255 | else |
1024 | _accum_0[_len_0] = i | 1256 | _accum_0[_len_0] = i |
1257 | _len_0 = _len_0 + 1 | ||
1025 | end | 1258 | end |
1026 | _len_0 = _len_0 + 1 | ||
1027 | end | 1259 | end |
1028 | doubled_evens = _accum_0 | 1260 | doubled_evens = _accum_0 |
1261 | local first_large | ||
1262 | local _accum_0 | ||
1263 | local _list_0 = numbers | ||
1264 | for _index_0 = 1, #_list_0 do | ||
1265 | local n = _list_0[_index_0] | ||
1266 | if n > 10 then | ||
1267 | _accum_0 = n | ||
1268 | break | ||
1269 | end | ||
1270 | end | ||
1271 | first_large = _accum_0 | ||
1029 | local func_a | 1272 | local func_a |
1030 | func_a = function() | 1273 | func_a = function() |
1031 | for i = 1, 10 do | 1274 | for i = 1, 10 do |
@@ -1174,7 +1417,7 @@ if "Robert" == name then | |||
1174 | elseif "Dan" == name or "Daniel" == name then | 1417 | elseif "Dan" == name or "Daniel" == name then |
1175 | print("ä½ çš„åå—æ˜¯Dan") | 1418 | print("ä½ çš„åå—æ˜¯Dan") |
1176 | else | 1419 | else |
1177 | print("我ä¸çŸ¥é“ä½ çš„åå—") | 1420 | print("我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯" .. tostring(name)) |
1178 | end | 1421 | end |
1179 | local b = 1 | 1422 | local b = 1 |
1180 | local next_number | 1423 | local next_number |
@@ -1274,6 +1517,192 @@ if _tab_0 then | |||
1274 | end | 1517 | end |
1275 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 1518 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
1276 | end | 1519 | end |
1520 | local _exp_0 = tb | ||
1521 | local _type_0 = type(_exp_0) | ||
1522 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1523 | local _match_0 = false | ||
1524 | if _tab_0 then | ||
1525 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
1526 | _match_0 = true | ||
1527 | print("1, 2, 3") | ||
1528 | end | ||
1529 | end | ||
1530 | if not _match_0 then | ||
1531 | local _match_1 = false | ||
1532 | if _tab_0 then | ||
1533 | local b = _exp_0[2] | ||
1534 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
1535 | _match_1 = true | ||
1536 | print("1, " .. tostring(b) .. ", 3") | ||
1537 | end | ||
1538 | end | ||
1539 | if not _match_1 then | ||
1540 | if _tab_0 then | ||
1541 | local b = _exp_0[3] | ||
1542 | if b == nil then | ||
1543 | b = 3 | ||
1544 | end | ||
1545 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
1546 | print("1, 2, " .. tostring(b)) | ||
1547 | end | ||
1548 | end | ||
1549 | end | ||
1550 | end | ||
1551 | local _exp_0 = tb | ||
1552 | local _type_0 = type(_exp_0) | ||
1553 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1554 | local _match_0 = false | ||
1555 | if _tab_0 then | ||
1556 | local result = _exp_0.result | ||
1557 | if true == _exp_0.success and result ~= nil then | ||
1558 | _match_0 = true | ||
1559 | print("æˆåŠŸ", result) | ||
1560 | end | ||
1561 | end | ||
1562 | if not _match_0 then | ||
1563 | local _match_1 = false | ||
1564 | if _tab_0 then | ||
1565 | if false == _exp_0.success then | ||
1566 | _match_1 = true | ||
1567 | print("失败", result) | ||
1568 | end | ||
1569 | end | ||
1570 | if not _match_1 then | ||
1571 | print("æ— æ•ˆå€¼") | ||
1572 | end | ||
1573 | end | ||
1574 | local _exp_0 = tb | ||
1575 | local _type_0 = type(_exp_0) | ||
1576 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1577 | local _match_0 = false | ||
1578 | if _tab_0 then | ||
1579 | local content | ||
1580 | do | ||
1581 | local _obj_0 = _exp_0.data | ||
1582 | local _type_1 = type(_obj_0) | ||
1583 | if "table" == _type_1 or "userdata" == _type_1 then | ||
1584 | content = _obj_0.content | ||
1585 | end | ||
1586 | end | ||
1587 | local _val_0 | ||
1588 | do | ||
1589 | local _obj_0 = _exp_0.data | ||
1590 | if _obj_0 ~= nil then | ||
1591 | _val_0 = _obj_0.type | ||
1592 | end | ||
1593 | end | ||
1594 | if "success" == _val_0 and content ~= nil then | ||
1595 | _match_0 = true | ||
1596 | print("æˆåŠŸ", content) | ||
1597 | end | ||
1598 | end | ||
1599 | if not _match_0 then | ||
1600 | local _match_1 = false | ||
1601 | if _tab_0 then | ||
1602 | local content | ||
1603 | do | ||
1604 | local _obj_0 = _exp_0.data | ||
1605 | local _type_1 = type(_obj_0) | ||
1606 | if "table" == _type_1 or "userdata" == _type_1 then | ||
1607 | content = _obj_0.content | ||
1608 | end | ||
1609 | end | ||
1610 | local _val_0 | ||
1611 | do | ||
1612 | local _obj_0 = _exp_0.data | ||
1613 | if _obj_0 ~= nil then | ||
1614 | _val_0 = _obj_0.type | ||
1615 | end | ||
1616 | end | ||
1617 | if "error" == _val_0 and content ~= nil then | ||
1618 | _match_1 = true | ||
1619 | print("失败", content) | ||
1620 | end | ||
1621 | end | ||
1622 | if not _match_1 then | ||
1623 | print("æ— æ•ˆå€¼") | ||
1624 | end | ||
1625 | end | ||
1626 | local _exp_0 = tb | ||
1627 | local _type_0 = type(_exp_0) | ||
1628 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1629 | if _tab_0 then | ||
1630 | local fourth = _exp_0[4] | ||
1631 | local _val_0 | ||
1632 | do | ||
1633 | local _obj_0 = _exp_0[1] | ||
1634 | if _obj_0 ~= nil then | ||
1635 | _val_0 = _obj_0.a | ||
1636 | end | ||
1637 | end | ||
1638 | local _val_1 | ||
1639 | do | ||
1640 | local _obj_0 = _exp_0[1] | ||
1641 | if _obj_0 ~= nil then | ||
1642 | _val_1 = _obj_0.b | ||
1643 | end | ||
1644 | end | ||
1645 | local _val_2 | ||
1646 | do | ||
1647 | local _obj_0 = _exp_0[2] | ||
1648 | if _obj_0 ~= nil then | ||
1649 | _val_2 = _obj_0.a | ||
1650 | end | ||
1651 | end | ||
1652 | local _val_3 | ||
1653 | do | ||
1654 | local _obj_0 = _exp_0[2] | ||
1655 | if _obj_0 ~= nil then | ||
1656 | _val_3 = _obj_0.b | ||
1657 | end | ||
1658 | end | ||
1659 | local _val_4 | ||
1660 | do | ||
1661 | local _obj_0 = _exp_0[3] | ||
1662 | if _obj_0 ~= nil then | ||
1663 | _val_4 = _obj_0.a | ||
1664 | end | ||
1665 | end | ||
1666 | local _val_5 | ||
1667 | do | ||
1668 | local _obj_0 = _exp_0[3] | ||
1669 | if _obj_0 ~= nil then | ||
1670 | _val_5 = _obj_0.b | ||
1671 | end | ||
1672 | end | ||
1673 | 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 | ||
1674 | print("åŒ¹é…æˆåŠŸ", fourth) | ||
1675 | end | ||
1676 | end | ||
1677 | local segments = { | ||
1678 | "admin", | ||
1679 | "users", | ||
1680 | "logs", | ||
1681 | "view" | ||
1682 | } | ||
1683 | local _type_0 = type(segments) | ||
1684 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
1685 | if _tab_0 then | ||
1686 | local groups | ||
1687 | do | ||
1688 | local _accum_0 = { } | ||
1689 | local _len_0 = 1 | ||
1690 | local _max_0 = #segments + -3 + 1 | ||
1691 | for _index_0 = 1, _max_0 do | ||
1692 | local _item_0 = segments[_index_0] | ||
1693 | _accum_0[_len_0] = _item_0 | ||
1694 | _len_0 = _len_0 + 1 | ||
1695 | end | ||
1696 | groups = _accum_0 | ||
1697 | end | ||
1698 | local resource = segments[#segments - 1] | ||
1699 | local action = segments[#segments] | ||
1700 | if resource ~= nil and action ~= nil then | ||
1701 | print("Group:", groups) | ||
1702 | print("Resource:", resource) | ||
1703 | print("Action:", action) | ||
1704 | end | ||
1705 | end | ||
1277 | local Inventory | 1706 | local Inventory |
1278 | local _class_0 | 1707 | local _class_0 |
1279 | local _base_0 = { | 1708 | local _base_0 = { |
@@ -1930,6 +2359,10 @@ do | |||
1930 | _with_1["key-name"] = value | 2359 | _with_1["key-name"] = value |
1931 | end | 2360 | end |
1932 | _with_0[#_with_0 + 1] = "abc" | 2361 | _with_0[#_with_0 + 1] = "abc" |
2362 | local _with_0 = obj | ||
2363 | if _with_0 ~= nil then | ||
2364 | print(obj.name) | ||
2365 | end | ||
1933 | do | 2366 | do |
1934 | local var = "hello" | 2367 | local var = "hello" |
1935 | print(var) | 2368 | print(var) |
@@ -2020,6 +2453,38 @@ local inventory = { | |||
2020 | } | 2453 | } |
2021 | } | 2454 | } |
2022 | } | 2455 | } |
2456 | local map | ||
2457 | map = function(arr, action) | ||
2458 | local _accum_0 = { } | ||
2459 | local _len_0 = 1 | ||
2460 | for _index_0 = 1, #arr do | ||
2461 | local item = arr[_index_0] | ||
2462 | _accum_0[_len_0] = action(item) | ||
2463 | _len_0 = _len_0 + 1 | ||
2464 | end | ||
2465 | return _accum_0 | ||
2466 | end | ||
2467 | local filter | ||
2468 | filter = function(arr, cond) | ||
2469 | local _accum_0 = { } | ||
2470 | local _len_0 = 1 | ||
2471 | for _index_0 = 1, #arr do | ||
2472 | local item = arr[_index_0] | ||
2473 | if cond(item) then | ||
2474 | _accum_0[_len_0] = item | ||
2475 | _len_0 = _len_0 + 1 | ||
2476 | end | ||
2477 | end | ||
2478 | return _accum_0 | ||
2479 | end | ||
2480 | local reduce | ||
2481 | reduce = function(arr, init, action) | ||
2482 | for _index_0 = 1, #arr do | ||
2483 | local item = arr[_index_0] | ||
2484 | init = action(init, item) | ||
2485 | end | ||
2486 | return init | ||
2487 | end | ||
2023 | print(reduce(filter(map({ | 2488 | print(reduce(filter(map({ |
2024 | 1, | 2489 | 1, |
2025 | 2, | 2490 | 2, |
@@ -2077,6 +2542,12 @@ end | |||
2077 | print("yuescript") | 2542 | print("yuescript") |
2078 | print(3) | 2543 | print(3) |
2079 | print("有效的枚举类型:", "Static") | 2544 | print("有效的枚举类型:", "Static") |
2545 | do | ||
2546 | print(123, "hello") | ||
2547 | end | ||
2548 | do | ||
2549 | print(123, "hello") | ||
2550 | end | ||
2080 | if tb ~= nil then | 2551 | if tb ~= nil then |
2081 | tb:func() | 2552 | tb:func() |
2082 | end | 2553 | end |
@@ -2177,6 +2648,16 @@ for _key_0, _value_0 in pairs(b) do | |||
2177 | end | 2648 | end |
2178 | end | 2649 | end |
2179 | merge = _tab_0 | 2650 | merge = _tab_0 |
2651 | local last | ||
2652 | do | ||
2653 | local _item_0 = data.items | ||
2654 | last = _item_0[#_item_0] | ||
2655 | end | ||
2656 | local second_last | ||
2657 | do | ||
2658 | local _item_0 = data.items | ||
2659 | second_last = _item_0[#_item_0 - 1] | ||
2660 | end | ||
2180 | local mt = { } | 2661 | local mt = { } |
2181 | local add | 2662 | local add |
2182 | add = function(self, right) | 2663 | add = function(self, right) |
@@ -2307,6 +2788,14 @@ func({ | |||
2307 | 2, | 2788 | 2, |
2308 | 3 | 2789 | 3 |
2309 | }) | 2790 | }) |
2791 | local f | ||
2792 | f = function() | ||
2793 | return { | ||
2794 | 1, | ||
2795 | 2, | ||
2796 | 3 | ||
2797 | } | ||
2798 | end | ||
2310 | local tb = { | 2799 | local tb = { |
2311 | name = "abc", | 2800 | name = "abc", |
2312 | values = { | 2801 | values = { |
@@ -2547,6 +3036,59 @@ end | |||
2547 | local two, four | 3036 | local two, four |
2548 | local _obj_0 = items | 3037 | local _obj_0 = items |
2549 | two, four = _obj_0[2], _obj_0[4] | 3038 | two, four = _obj_0[2], _obj_0[4] |
3039 | local orders = { | ||
3040 | "first", | ||
3041 | "second", | ||
3042 | "third", | ||
3043 | "fourth", | ||
3044 | "last" | ||
3045 | } | ||
3046 | local first, bulk, last = orders[1], (function() | ||
3047 | local _accum_0 = { } | ||
3048 | local _len_0 = 1 | ||
3049 | local _max_0 = #orders + -2 + 1 | ||
3050 | for _index_0 = 2, _max_0 do | ||
3051 | local _item_0 = orders[_index_0] | ||
3052 | _accum_0[_len_0] = _item_0 | ||
3053 | _len_0 = _len_0 + 1 | ||
3054 | end | ||
3055 | return _accum_0 | ||
3056 | end)(), orders[#orders] | ||
3057 | print(first) | ||
3058 | print(bulk) | ||
3059 | print(last) | ||
3060 | local first, rest | ||
3061 | do | ||
3062 | local _obj_0 = orders | ||
3063 | first, rest = _obj_0[1], (function() | ||
3064 | local _accum_0 = { } | ||
3065 | local _len_0 = 1 | ||
3066 | local _max_0 = #_obj_0 | ||
3067 | for _index_0 = 2, _max_0 do | ||
3068 | local _item_0 = _obj_0[_index_0] | ||
3069 | _accum_0[_len_0] = _item_0 | ||
3070 | _len_0 = _len_0 + 1 | ||
3071 | end | ||
3072 | return _accum_0 | ||
3073 | end)() | ||
3074 | end | ||
3075 | local start, last | ||
3076 | do | ||
3077 | local _obj_0 = orders | ||
3078 | start, last = (function() | ||
3079 | local _accum_0 = { } | ||
3080 | local _len_0 = 1 | ||
3081 | local _max_0 = #_obj_0 + -2 + 1 | ||
3082 | for _index_0 = 1, _max_0 do | ||
3083 | local _item_0 = _obj_0[_index_0] | ||
3084 | _accum_0[_len_0] = _item_0 | ||
3085 | _len_0 = _len_0 + 1 | ||
3086 | end | ||
3087 | return _accum_0 | ||
3088 | end)(), _obj_0[#_obj_0] | ||
3089 | end | ||
3090 | local _obj_0 = orders | ||
3091 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
2550 | local tuples = { | 3092 | local tuples = { |
2551 | { | 3093 | { |
2552 | "hello", | 3094 | "hello", |
@@ -2648,6 +3190,56 @@ end) | |||
2648 | if success then | 3190 | if success then |
2649 | print(result) | 3191 | print(result) |
2650 | end | 3192 | end |
3193 | local a, b, c | ||
3194 | do | ||
3195 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
3196 | return func() | ||
3197 | end) | ||
3198 | if _ok_0 then | ||
3199 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
3200 | end | ||
3201 | end | ||
3202 | do | ||
3203 | local _exp_0 = ((function() | ||
3204 | return (function(_arg_0, ...) | ||
3205 | local _ok_0 = _arg_0 | ||
3206 | if _ok_0 then | ||
3207 | return ... | ||
3208 | end | ||
3209 | end)(pcall(function() | ||
3210 | return func() | ||
3211 | end)) | ||
3212 | end)()) | ||
3213 | if _exp_0 ~= nil then | ||
3214 | a = _exp_0 | ||
3215 | else | ||
3216 | a = "default" | ||
3217 | end | ||
3218 | end | ||
3219 | f((function() | ||
3220 | return (function(_arg_0, ...) | ||
3221 | local _ok_0 = _arg_0 | ||
3222 | if _ok_0 then | ||
3223 | return ... | ||
3224 | end | ||
3225 | end)(pcall(function() | ||
3226 | return func() | ||
3227 | end)) | ||
3228 | end)()) | ||
3229 | f((function() | ||
3230 | return (function(_arg_0, ...) | ||
3231 | local _ok_0 = _arg_0 | ||
3232 | if _ok_0 then | ||
3233 | return ... | ||
3234 | end | ||
3235 | end)(xpcall(function() | ||
3236 | print(123) | ||
3237 | return func() | ||
3238 | end, function(e) | ||
3239 | print(e) | ||
3240 | return e | ||
3241 | end)) | ||
3242 | end)()) | ||
2651 | local a <const> = 123 | 3243 | local a <const> = 123 |
2652 | local _ <close> = setmetatable({ }, { | 3244 | local _ <close> = setmetatable({ }, { |
2653 | __close = function() | 3245 | __close = function() |
@@ -2657,10 +3249,19 @@ local _ <close> = setmetatable({ }, { | |||
2657 | local a, b, c, d | 3249 | local a, b, c, d |
2658 | local _obj_0 = tb | 3250 | local _obj_0 = tb |
2659 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 3251 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
3252 | Constant = 123 | ||
2660 | local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" | 3253 | local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" |
2661 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") | 3254 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") |
2662 | local integer = 1000000 | 3255 | local integer = 1000000 |
2663 | local hex = 0xEFBBBF | 3256 | local hex = 0xEFBBBF |
3257 | local binary = 19 | ||
3258 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
3259 | local fn | ||
3260 | fn = function() | ||
3261 | local str = "foo:\n bar: baz" | ||
3262 | return str | ||
3263 | end | ||
3264 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
2664 | local my_function | 3265 | local my_function |
2665 | my_function = function() end | 3266 | my_function = function() end |
2666 | my_function() | 3267 | my_function() |
@@ -2749,6 +3350,66 @@ if func(1, 2, 3, "ä½ å¥½", "世界") then | |||
2749 | print("ä½ å¥½") | 3350 | print("ä½ å¥½") |
2750 | print("我在if内部") | 3351 | print("我在if内部") |
2751 | end | 3352 | end |
3353 | local f1 | ||
3354 | f1 = function(_arg_0) | ||
3355 | local a, b, c | ||
3356 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
3357 | return print(a, b, c) | ||
3358 | end | ||
3359 | f1({ | ||
3360 | a = 1, | ||
3361 | b = "2", | ||
3362 | c = { } | ||
3363 | }) | ||
3364 | local f2 | ||
3365 | f2 = function(_arg_0, c) | ||
3366 | local a1, b | ||
3367 | a1, b = _arg_0.a, _arg_0.b | ||
3368 | if a1 == nil then | ||
3369 | a1 = 123 | ||
3370 | end | ||
3371 | if b == nil then | ||
3372 | b = 'abc' | ||
3373 | end | ||
3374 | if c == nil then | ||
3375 | c = { } | ||
3376 | end | ||
3377 | return print(a1, b, c) | ||
3378 | end | ||
3379 | local arg1 = { | ||
3380 | a = 0 | ||
3381 | } | ||
3382 | f2(arg1, arg2) | ||
3383 | local findFirstEven | ||
3384 | findFirstEven = function(list) | ||
3385 | for _index_0 = 1, #list do | ||
3386 | local item = list[_index_0] | ||
3387 | if type(item) == "table" then | ||
3388 | for _index_1 = 1, #item do | ||
3389 | local sub = item[_index_1] | ||
3390 | if sub % 2 == 0 then | ||
3391 | return sub | ||
3392 | end | ||
3393 | end | ||
3394 | end | ||
3395 | end | ||
3396 | return nil | ||
3397 | end | ||
3398 | local findFirstEven | ||
3399 | findFirstEven = function(list) | ||
3400 | for _index_0 = 1, #list do | ||
3401 | local item = list[_index_0] | ||
3402 | if type(item) == "table" then | ||
3403 | for _index_1 = 1, #item do | ||
3404 | local sub = item[_index_1] | ||
3405 | if sub % 2 == 0 then | ||
3406 | return sub | ||
3407 | end | ||
3408 | end | ||
3409 | end | ||
3410 | end | ||
3411 | return nil | ||
3412 | end | ||
2752 | f(function() | 3413 | f(function() |
2753 | return print("hello") | 3414 | return print("hello") |
2754 | end) | 3415 | end) |
@@ -2964,8 +3625,7 @@ local slice | |||
2964 | local _accum_0 = { } | 3625 | local _accum_0 = { } |
2965 | local _len_0 = 1 | 3626 | local _len_0 = 1 |
2966 | local _list_0 = items | 3627 | local _list_0 = items |
2967 | local _max_0 = 5 | 3628 | for _index_0 = 1, 5 do |
2968 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
2969 | local item = _list_0[_index_0] | 3629 | local item = _list_0[_index_0] |
2970 | _accum_0[_len_0] = item | 3630 | _accum_0[_len_0] = item |
2971 | _len_0 = _len_0 + 1 | 3631 | _len_0 = _len_0 + 1 |
@@ -2975,7 +3635,8 @@ local slice | |||
2975 | local _accum_0 = { } | 3635 | local _accum_0 = { } |
2976 | local _len_0 = 1 | 3636 | local _len_0 = 1 |
2977 | local _list_0 = items | 3637 | local _list_0 = items |
2978 | for _index_0 = 2, #_list_0 do | 3638 | local _max_0 = #_list_0 |
3639 | for _index_0 = 2, _max_0 do | ||
2979 | local item = _list_0[_index_0] | 3640 | local item = _list_0[_index_0] |
2980 | _accum_0[_len_0] = item | 3641 | _accum_0[_len_0] = item |
2981 | _len_0 = _len_0 + 1 | 3642 | _len_0 = _len_0 + 1 |
@@ -2985,12 +3646,46 @@ local slice | |||
2985 | local _accum_0 = { } | 3646 | local _accum_0 = { } |
2986 | local _len_0 = 1 | 3647 | local _len_0 = 1 |
2987 | local _list_0 = items | 3648 | local _list_0 = items |
2988 | for _index_0 = 1, #_list_0, 2 do | 3649 | local _max_0 = #_list_0 |
3650 | for _index_0 = 1, _max_0, 2 do | ||
2989 | local item = _list_0[_index_0] | 3651 | local item = _list_0[_index_0] |
2990 | _accum_0[_len_0] = item | 3652 | _accum_0[_len_0] = item |
2991 | _len_0 = _len_0 + 1 | 3653 | _len_0 = _len_0 + 1 |
2992 | end | 3654 | end |
2993 | slice = _accum_0 | 3655 | slice = _accum_0 |
3656 | local slice | ||
3657 | local _accum_0 = { } | ||
3658 | local _len_0 = 1 | ||
3659 | local _list_0 = items | ||
3660 | local _min_0 = #_list_0 + -4 + 1 | ||
3661 | local _max_0 = #_list_0 + -1 + 1 | ||
3662 | for _index_0 = _min_0, _max_0 do | ||
3663 | local item = _list_0[_index_0] | ||
3664 | _accum_0[_len_0] = item | ||
3665 | _len_0 = _len_0 + 1 | ||
3666 | end | ||
3667 | slice = _accum_0 | ||
3668 | local reverse_slice | ||
3669 | local _accum_0 = { } | ||
3670 | local _len_0 = 1 | ||
3671 | local _list_0 = items | ||
3672 | local _min_0 = #_list_0 + -1 + 1 | ||
3673 | for _index_0 = _min_0, 1, -1 do | ||
3674 | local item = _list_0[_index_0] | ||
3675 | _accum_0[_len_0] = item | ||
3676 | _len_0 = _len_0 + 1 | ||
3677 | end | ||
3678 | reverse_slice = _accum_0 | ||
3679 | local sub_list | ||
3680 | local _accum_0 = { } | ||
3681 | local _len_0 = 1 | ||
3682 | local _list_0 = items | ||
3683 | for _index_0 = 2, 4 do | ||
3684 | local _item_0 = _list_0[_index_0] | ||
3685 | _accum_0[_len_0] = _item_0 | ||
3686 | _len_0 = _len_0 + 1 | ||
3687 | end | ||
3688 | sub_list = _accum_0 | ||
2994 | for i = 10, 20 do | 3689 | for i = 10, 20 do |
2995 | print(i) | 3690 | print(i) |
2996 | end | 3691 | end |
@@ -3001,8 +3696,7 @@ for key, value in pairs(object) do | |||
3001 | print(key, value) | 3696 | print(key, value) |
3002 | end | 3697 | end |
3003 | local _list_0 = items | 3698 | local _list_0 = items |
3004 | local _max_0 = 4 | 3699 | for _index_0 = 2, 4 do |
3005 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
3006 | local item = _list_0[_index_0] | 3700 | local item = _list_0[_index_0] |
3007 | print(item) | 3701 | print(item) |
3008 | end | 3702 | end |
@@ -3020,12 +3714,24 @@ local _len_0 = 1 | |||
3020 | for i = 1, 20 do | 3714 | for i = 1, 20 do |
3021 | if i % 2 == 0 then | 3715 | if i % 2 == 0 then |
3022 | _accum_0[_len_0] = i * 2 | 3716 | _accum_0[_len_0] = i * 2 |
3717 | _len_0 = _len_0 + 1 | ||
3023 | else | 3718 | else |
3024 | _accum_0[_len_0] = i | 3719 | _accum_0[_len_0] = i |
3720 | _len_0 = _len_0 + 1 | ||
3025 | end | 3721 | end |
3026 | _len_0 = _len_0 + 1 | ||
3027 | end | 3722 | end |
3028 | doubled_evens = _accum_0 | 3723 | doubled_evens = _accum_0 |
3724 | local first_large | ||
3725 | local _accum_0 | ||
3726 | local _list_0 = numbers | ||
3727 | for _index_0 = 1, #_list_0 do | ||
3728 | local n = _list_0[_index_0] | ||
3729 | if n > 10 then | ||
3730 | _accum_0 = n | ||
3731 | break | ||
3732 | end | ||
3733 | end | ||
3734 | first_large = _accum_0 | ||
3029 | local func_a | 3735 | local func_a |
3030 | func_a = function() | 3736 | func_a = function() |
3031 | for i = 1, 10 do | 3737 | for i = 1, 10 do |
@@ -3174,7 +3880,7 @@ if "Robert" == name then | |||
3174 | elseif "Dan" == name or "Daniel" == name then | 3880 | elseif "Dan" == name or "Daniel" == name then |
3175 | print("ä½ çš„åå—æ˜¯Dan") | 3881 | print("ä½ çš„åå—æ˜¯Dan") |
3176 | else | 3882 | else |
3177 | print("我ä¸çŸ¥é“ä½ çš„åå—") | 3883 | print("我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯" .. tostring(name)) |
3178 | end | 3884 | end |
3179 | local b = 1 | 3885 | local b = 1 |
3180 | local next_number | 3886 | local next_number |
@@ -3274,6 +3980,192 @@ if _tab_0 then | |||
3274 | end | 3980 | end |
3275 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 3981 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
3276 | end | 3982 | end |
3983 | local _exp_0 = tb | ||
3984 | local _type_0 = type(_exp_0) | ||
3985 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
3986 | local _match_0 = false | ||
3987 | if _tab_0 then | ||
3988 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
3989 | _match_0 = true | ||
3990 | print("1, 2, 3") | ||
3991 | end | ||
3992 | end | ||
3993 | if not _match_0 then | ||
3994 | local _match_1 = false | ||
3995 | if _tab_0 then | ||
3996 | local b = _exp_0[2] | ||
3997 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
3998 | _match_1 = true | ||
3999 | print("1, " .. tostring(b) .. ", 3") | ||
4000 | end | ||
4001 | end | ||
4002 | if not _match_1 then | ||
4003 | if _tab_0 then | ||
4004 | local b = _exp_0[3] | ||
4005 | if b == nil then | ||
4006 | b = 3 | ||
4007 | end | ||
4008 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
4009 | print("1, 2, " .. tostring(b)) | ||
4010 | end | ||
4011 | end | ||
4012 | end | ||
4013 | end | ||
4014 | local _exp_0 = tb | ||
4015 | local _type_0 = type(_exp_0) | ||
4016 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4017 | local _match_0 = false | ||
4018 | if _tab_0 then | ||
4019 | local result = _exp_0.result | ||
4020 | if true == _exp_0.success and result ~= nil then | ||
4021 | _match_0 = true | ||
4022 | print("æˆåŠŸ", result) | ||
4023 | end | ||
4024 | end | ||
4025 | if not _match_0 then | ||
4026 | local _match_1 = false | ||
4027 | if _tab_0 then | ||
4028 | if false == _exp_0.success then | ||
4029 | _match_1 = true | ||
4030 | print("失败", result) | ||
4031 | end | ||
4032 | end | ||
4033 | if not _match_1 then | ||
4034 | print("æ— æ•ˆå€¼") | ||
4035 | end | ||
4036 | end | ||
4037 | local _exp_0 = tb | ||
4038 | local _type_0 = type(_exp_0) | ||
4039 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4040 | local _match_0 = false | ||
4041 | if _tab_0 then | ||
4042 | local content | ||
4043 | do | ||
4044 | local _obj_0 = _exp_0.data | ||
4045 | local _type_1 = type(_obj_0) | ||
4046 | if "table" == _type_1 or "userdata" == _type_1 then | ||
4047 | content = _obj_0.content | ||
4048 | end | ||
4049 | end | ||
4050 | local _val_0 | ||
4051 | do | ||
4052 | local _obj_0 = _exp_0.data | ||
4053 | if _obj_0 ~= nil then | ||
4054 | _val_0 = _obj_0.type | ||
4055 | end | ||
4056 | end | ||
4057 | if "success" == _val_0 and content ~= nil then | ||
4058 | _match_0 = true | ||
4059 | print("æˆåŠŸ", content) | ||
4060 | end | ||
4061 | end | ||
4062 | if not _match_0 then | ||
4063 | local _match_1 = false | ||
4064 | if _tab_0 then | ||
4065 | local content | ||
4066 | do | ||
4067 | local _obj_0 = _exp_0.data | ||
4068 | local _type_1 = type(_obj_0) | ||
4069 | if "table" == _type_1 or "userdata" == _type_1 then | ||
4070 | content = _obj_0.content | ||
4071 | end | ||
4072 | end | ||
4073 | local _val_0 | ||
4074 | do | ||
4075 | local _obj_0 = _exp_0.data | ||
4076 | if _obj_0 ~= nil then | ||
4077 | _val_0 = _obj_0.type | ||
4078 | end | ||
4079 | end | ||
4080 | if "error" == _val_0 and content ~= nil then | ||
4081 | _match_1 = true | ||
4082 | print("失败", content) | ||
4083 | end | ||
4084 | end | ||
4085 | if not _match_1 then | ||
4086 | print("æ— æ•ˆå€¼") | ||
4087 | end | ||
4088 | end | ||
4089 | local _exp_0 = tb | ||
4090 | local _type_0 = type(_exp_0) | ||
4091 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4092 | if _tab_0 then | ||
4093 | local fourth = _exp_0[4] | ||
4094 | local _val_0 | ||
4095 | do | ||
4096 | local _obj_0 = _exp_0[1] | ||
4097 | if _obj_0 ~= nil then | ||
4098 | _val_0 = _obj_0.a | ||
4099 | end | ||
4100 | end | ||
4101 | local _val_1 | ||
4102 | do | ||
4103 | local _obj_0 = _exp_0[1] | ||
4104 | if _obj_0 ~= nil then | ||
4105 | _val_1 = _obj_0.b | ||
4106 | end | ||
4107 | end | ||
4108 | local _val_2 | ||
4109 | do | ||
4110 | local _obj_0 = _exp_0[2] | ||
4111 | if _obj_0 ~= nil then | ||
4112 | _val_2 = _obj_0.a | ||
4113 | end | ||
4114 | end | ||
4115 | local _val_3 | ||
4116 | do | ||
4117 | local _obj_0 = _exp_0[2] | ||
4118 | if _obj_0 ~= nil then | ||
4119 | _val_3 = _obj_0.b | ||
4120 | end | ||
4121 | end | ||
4122 | local _val_4 | ||
4123 | do | ||
4124 | local _obj_0 = _exp_0[3] | ||
4125 | if _obj_0 ~= nil then | ||
4126 | _val_4 = _obj_0.a | ||
4127 | end | ||
4128 | end | ||
4129 | local _val_5 | ||
4130 | do | ||
4131 | local _obj_0 = _exp_0[3] | ||
4132 | if _obj_0 ~= nil then | ||
4133 | _val_5 = _obj_0.b | ||
4134 | end | ||
4135 | end | ||
4136 | 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 | ||
4137 | print("åŒ¹é…æˆåŠŸ", fourth) | ||
4138 | end | ||
4139 | end | ||
4140 | local segments = { | ||
4141 | "admin", | ||
4142 | "users", | ||
4143 | "logs", | ||
4144 | "view" | ||
4145 | } | ||
4146 | local _type_0 = type(segments) | ||
4147 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
4148 | if _tab_0 then | ||
4149 | local groups | ||
4150 | do | ||
4151 | local _accum_0 = { } | ||
4152 | local _len_0 = 1 | ||
4153 | local _max_0 = #segments + -3 + 1 | ||
4154 | for _index_0 = 1, _max_0 do | ||
4155 | local _item_0 = segments[_index_0] | ||
4156 | _accum_0[_len_0] = _item_0 | ||
4157 | _len_0 = _len_0 + 1 | ||
4158 | end | ||
4159 | groups = _accum_0 | ||
4160 | end | ||
4161 | local resource = segments[#segments - 1] | ||
4162 | local action = segments[#segments] | ||
4163 | if resource ~= nil and action ~= nil then | ||
4164 | print("Group:", groups) | ||
4165 | print("Resource:", resource) | ||
4166 | print("Action:", action) | ||
4167 | end | ||
4168 | end | ||
3277 | local Inventory | 4169 | local Inventory |
3278 | local _class_0 | 4170 | local _class_0 |
3279 | local _base_0 = { | 4171 | local _base_0 = { |
@@ -3930,6 +4822,10 @@ do | |||
3930 | _with_1["key-name"] = value | 4822 | _with_1["key-name"] = value |
3931 | end | 4823 | end |
3932 | _with_0[#_with_0 + 1] = "abc" | 4824 | _with_0[#_with_0 + 1] = "abc" |
4825 | local _with_0 = obj | ||
4826 | if _with_0 ~= nil then | ||
4827 | print(obj.name) | ||
4828 | end | ||
3933 | do | 4829 | do |
3934 | local var = "hello" | 4830 | local var = "hello" |
3935 | print(var) | 4831 | print(var) |
diff --git a/spec/outputs/comprehension.lua b/spec/outputs/comprehension.lua index 9a7c478..663bd44 100644 --- a/spec/outputs/comprehension.lua +++ b/spec/outputs/comprehension.lua | |||
@@ -243,8 +243,11 @@ end | |||
243 | do | 243 | do |
244 | local _accum_0 = { } | 244 | local _accum_0 = { } |
245 | local _len_0 = 1 | 245 | local _len_0 = 1 |
246 | local _min_0 = 1 + 2 | ||
246 | local _max_0 = 3 + 4 | 247 | local _max_0 = 3 + 4 |
247 | for _index_0 = 1 + 2, _max_0 < 0 and #items + _max_0 or _max_0 do | 248 | _min_0 = _min_0 < 0 and #items + _min_0 + 1 or _min_0 |
249 | _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 | ||
250 | for _index_0 = _min_0, _max_0 do | ||
248 | local item = items[_index_0] | 251 | local item = items[_index_0] |
249 | _accum_0[_len_0] = item | 252 | _accum_0[_len_0] = item |
250 | _len_0 = _len_0 + 1 | 253 | _len_0 = _len_0 + 1 |
@@ -254,8 +257,11 @@ end | |||
254 | do | 257 | do |
255 | local _accum_0 = { } | 258 | local _accum_0 = { } |
256 | local _len_0 = 1 | 259 | local _len_0 = 1 |
260 | local _min_0 = hello() * 4 | ||
257 | local _max_0 = 2 - thing[4] | 261 | local _max_0 = 2 - thing[4] |
258 | for _index_0 = hello() * 4, _max_0 < 0 and #items + _max_0 or _max_0 do | 262 | _min_0 = _min_0 < 0 and #items + _min_0 + 1 or _min_0 |
263 | _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 | ||
264 | for _index_0 = _min_0, _max_0 do | ||
259 | local item = items[_index_0] | 265 | local item = items[_index_0] |
260 | _accum_0[_len_0] = item | 266 | _accum_0[_len_0] = item |
261 | _len_0 = _len_0 + 1 | 267 | _len_0 = _len_0 + 1 |
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 44da58b..ba216b5 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua | |||
@@ -621,4 +621,94 @@ do | |||
621 | print(meta_field, abc, def) | 621 | print(meta_field, abc, def) |
622 | end | 622 | end |
623 | end | 623 | end |
624 | do | ||
625 | local clients = { | ||
626 | "VIP_Alice", | ||
627 | "User_Bob", | ||
628 | "User_Clara", | ||
629 | "VIP_Eva" | ||
630 | } | ||
631 | local vipStart, regulars, vipEnd = clients[1], (function() | ||
632 | local _accum_0 = { } | ||
633 | local _len_0 = 1 | ||
634 | local _max_0 = #clients + -2 + 1 | ||
635 | for _index_0 = 2, _max_0 do | ||
636 | local _item_0 = clients[_index_0] | ||
637 | _accum_0[_len_0] = _item_0 | ||
638 | _len_0 = _len_0 + 1 | ||
639 | end | ||
640 | return _accum_0 | ||
641 | end)(), clients[#clients] | ||
642 | print(vipStart) | ||
643 | print(regulars) | ||
644 | print(vipEnd) | ||
645 | end | ||
646 | do | ||
647 | local setupMeeting | ||
648 | setupMeeting = function(participants) | ||
649 | local chair, secretary = participants[1], participants[#participants] | ||
650 | return print(chair, secretary) | ||
651 | end | ||
652 | setupMeeting({ | ||
653 | "Alice", | ||
654 | "Bob", | ||
655 | "Charlie", | ||
656 | "David" | ||
657 | }) | ||
658 | end | ||
659 | do | ||
660 | local getTransactions | ||
661 | getTransactions = function() | ||
662 | return { | ||
663 | { | ||
664 | id = "T1", | ||
665 | amount = 100 | ||
666 | }, | ||
667 | { | ||
668 | id = "T2", | ||
669 | amount = 200 | ||
670 | }, | ||
671 | { | ||
672 | id = "T3", | ||
673 | amount = 300 | ||
674 | } | ||
675 | } | ||
676 | end | ||
677 | local id, amount | ||
678 | do | ||
679 | local _item_0 = getTransactions() | ||
680 | local _obj_0 = _item_0[#_item_0] | ||
681 | id, amount = _obj_0.id, _obj_0.amount | ||
682 | end | ||
683 | assert(id == "T3") | ||
684 | assert(amount == 300) | ||
685 | end | ||
686 | do | ||
687 | local middle | ||
688 | local _accum_0 = { } | ||
689 | local _len_0 = 1 | ||
690 | local _list_0 = tb | ||
691 | local _max_0 = #_list_0 + -2 + 1 | ||
692 | for _index_0 = 2, _max_0 do | ||
693 | local _item_0 = _list_0[_index_0] | ||
694 | _accum_0[_len_0] = _item_0 | ||
695 | _len_0 = _len_0 + 1 | ||
696 | end | ||
697 | middle = _accum_0 | ||
698 | end | ||
699 | do | ||
700 | local a, abc, b, def, sub, d, e | ||
701 | local _obj_0 = tb | ||
702 | a, abc, b, def, sub, d, e = _obj_0[1], _obj_0.abc, _obj_0[2], _obj_0.def, (function() | ||
703 | local _accum_0 = { } | ||
704 | local _len_0 = 1 | ||
705 | local _max_0 = #_obj_0 + -3 + 1 | ||
706 | for _index_0 = 3, _max_0 do | ||
707 | local _item_0 = _obj_0[_index_0] | ||
708 | _accum_0[_len_0] = _item_0 | ||
709 | _len_0 = _len_0 + 1 | ||
710 | end | ||
711 | return _accum_0 | ||
712 | end)(), _obj_0[#_obj_0 - 1], _obj_0[#_obj_0] | ||
713 | end | ||
624 | return nil | 714 | return nil |
diff --git a/spec/outputs/funcs.lua b/spec/outputs/funcs.lua index c1735c4..db7ed67 100644 --- a/spec/outputs/funcs.lua +++ b/spec/outputs/funcs.lua | |||
@@ -283,4 +283,157 @@ do | |||
283 | end | 283 | end |
284 | print(func()) | 284 | print(func()) |
285 | end | 285 | end |
286 | local _anon_func_0 = function(_arg_0) | ||
287 | local _accum_0 = { } | ||
288 | local _len_0 = 1 | ||
289 | local _max_0 = #_arg_0 | ||
290 | for _index_0 = 1, _max_0 do | ||
291 | local _item_0 = _arg_0[_index_0] | ||
292 | _accum_0[_len_0] = _item_0 | ||
293 | _len_0 = _len_0 + 1 | ||
294 | end | ||
295 | return _accum_0 | ||
296 | end | ||
297 | do | ||
298 | local f | ||
299 | f = function(_arg_0) | ||
300 | local a, b, c | ||
301 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
302 | return print(a, b, c) | ||
303 | end | ||
304 | f = function(_arg_0) | ||
305 | local a, b, c | ||
306 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
307 | return print(a, b, c) | ||
308 | end | ||
309 | local g | ||
310 | g = function(x, _arg_0) | ||
311 | local y | ||
312 | y = _arg_0.y | ||
313 | return print(x, y) | ||
314 | end | ||
315 | local i | ||
316 | i = function(_arg_0) | ||
317 | local ax, by | ||
318 | ax, by = _arg_0.a, _arg_0.b | ||
319 | if ax == nil then | ||
320 | ax = 0 | ||
321 | end | ||
322 | if by == nil then | ||
323 | by = 0 | ||
324 | end | ||
325 | return print(ax, by) | ||
326 | end | ||
327 | j = function(name, _arg_0) | ||
328 | local uid, role | ||
329 | uid, role = _arg_0.id, _arg_0.role | ||
330 | if uid == nil then | ||
331 | uid = "n/a" | ||
332 | end | ||
333 | if role == nil then | ||
334 | role = "guest" | ||
335 | end | ||
336 | return print(name, uid, role) | ||
337 | end | ||
338 | local m | ||
339 | m = function(_arg_0) | ||
340 | local name, age, ver | ||
341 | name, age, ver = _arg_0.user.name, _arg_0.user.age, _arg_0.meta.ver | ||
342 | if ver == nil then | ||
343 | ver = 1 | ||
344 | end | ||
345 | return print(name, age, ver) | ||
346 | end | ||
347 | local m1 | ||
348 | m1 = function(_arg_0) | ||
349 | local name, age, meta | ||
350 | name, age, meta = _arg_0.user.name, _arg_0.user.age, _arg_0.meta | ||
351 | if meta == nil then | ||
352 | meta = { } | ||
353 | end | ||
354 | return print(name, age, meta and meta.ver or "nil") | ||
355 | end | ||
356 | local new | ||
357 | new = function(self, _arg_0) | ||
358 | local name, age | ||
359 | name, age = _arg_0.name, _arg_0.age | ||
360 | if name == nil then | ||
361 | name = "anon" | ||
362 | end | ||
363 | if age == nil then | ||
364 | age = 0 | ||
365 | end | ||
366 | self.name = name | ||
367 | self.age = age | ||
368 | end | ||
369 | local set | ||
370 | set = function(self, _arg_0) | ||
371 | local name, age | ||
372 | name, age = _arg_0.name, _arg_0.age | ||
373 | if name == nil then | ||
374 | name = self.name | ||
375 | end | ||
376 | if age == nil then | ||
377 | age = self.age | ||
378 | end | ||
379 | self.name = name | ||
380 | self.age = age | ||
381 | end | ||
382 | local logKV | ||
383 | logKV = function(_arg_0, ...) | ||
384 | local k, v | ||
385 | k, v = _arg_0.k, _arg_0.v | ||
386 | print("kv:", k, v) | ||
387 | return print("rest count:", select("#", ...)) | ||
388 | end | ||
389 | do | ||
390 | local foo | ||
391 | foo = function(_arg_0) | ||
392 | local a, b | ||
393 | a, b = _arg_0.a, _arg_0.b | ||
394 | if b == nil then | ||
395 | b = 0 | ||
396 | end | ||
397 | return print(a, b) | ||
398 | end | ||
399 | end | ||
400 | local t1 | ||
401 | t1 = function(_arg_0, x) | ||
402 | local a | ||
403 | a = _arg_0.a | ||
404 | return print(a, x) | ||
405 | end | ||
406 | local t2 | ||
407 | t2 = function(_arg_0) | ||
408 | local a | ||
409 | a = _arg_0.a | ||
410 | return print(a) | ||
411 | end | ||
412 | local w | ||
413 | w = function(id, _arg_0, _arg_1) | ||
414 | local x, y | ||
415 | x, y = _arg_0.x, _arg_0.y | ||
416 | if x == nil then | ||
417 | x = 0 | ||
418 | end | ||
419 | if y == nil then | ||
420 | y = 0 | ||
421 | end | ||
422 | local flag | ||
423 | flag = _arg_1.flag | ||
424 | return print(id, x, y, flag) | ||
425 | end | ||
426 | local g1 | ||
427 | g1 = function(_arg_0) | ||
428 | local a, ax | ||
429 | a, ax = _arg_0.a, _arg_0.a | ||
430 | return print(a, ax) | ||
431 | end | ||
432 | local g4 | ||
433 | g4 = function(_arg_0) | ||
434 | local a, b, rest | ||
435 | a, b, rest = _arg_0.a, _arg_0.b, _anon_func_0(_arg_0) | ||
436 | return print(a, b) | ||
437 | end | ||
438 | end | ||
286 | return nil | 439 | return nil |
diff --git a/spec/outputs/global.lua b/spec/outputs/global.lua index 54a21a9..3918f85 100644 --- a/spec/outputs/global.lua +++ b/spec/outputs/global.lua | |||
@@ -93,3 +93,28 @@ do | |||
93 | FooBar = "pascal case" | 93 | FooBar = "pascal case" |
94 | FOOBAR = "all uppercase" | 94 | FOOBAR = "all uppercase" |
95 | end | 95 | end |
96 | do | ||
97 | do | ||
98 | local _class_0 | ||
99 | local _base_0 = { } | ||
100 | if _base_0.__index == nil then | ||
101 | _base_0.__index = _base_0 | ||
102 | end | ||
103 | _class_0 = setmetatable({ | ||
104 | __init = function() end, | ||
105 | __base = _base_0, | ||
106 | __name = "A" | ||
107 | }, { | ||
108 | __index = _base_0, | ||
109 | __call = function(cls, ...) | ||
110 | local _self_0 = setmetatable({ }, _base_0) | ||
111 | cls.__init(_self_0, ...) | ||
112 | return _self_0 | ||
113 | end | ||
114 | }) | ||
115 | _base_0.__class = _class_0 | ||
116 | A = _class_0 | ||
117 | end | ||
118 | Flag = 1 | ||
119 | const, x, y = "const", 1, 2 | ||
120 | end | ||
diff --git a/spec/outputs/import.lua b/spec/outputs/import.lua index 83c99e2..7aa130f 100644 --- a/spec/outputs/import.lua +++ b/spec/outputs/import.lua | |||
@@ -166,3 +166,13 @@ do | |||
166 | local _obj_1 = require("m") | 166 | local _obj_1 = require("m") |
167 | g, i = _obj_1[1], getmetatable(_obj_1[2]).__close | 167 | g, i = _obj_1[1], getmetatable(_obj_1[2]).__close |
168 | end | 168 | end |
169 | do | ||
170 | local require <const> = require | ||
171 | local stringlib <const> = string | ||
172 | local format <const> = string.format | ||
173 | local io_read <const> = io.read | ||
174 | local type | ||
175 | type = function() end | ||
176 | local tp <const> = _G.type | ||
177 | local yue <const> = _G["月"] | ||
178 | end | ||
diff --git a/spec/outputs/lists.lua b/spec/outputs/lists.lua index 48ec9c8..2ed7b95 100644 --- a/spec/outputs/lists.lua +++ b/spec/outputs/lists.lua | |||
@@ -230,31 +230,36 @@ x = { | |||
230 | 6, | 230 | 6, |
231 | 7 | 231 | 7 |
232 | } | 232 | } |
233 | local _max_0 = -5 | 233 | local _max_0 = #x + -5 + 1 |
234 | for _index_0 = 2, _max_0 < 0 and #x + _max_0 or _max_0, 2 do | 234 | for _index_0 = 2, _max_0, 2 do |
235 | local y = x[_index_0] | 235 | local y = x[_index_0] |
236 | print(y) | 236 | print(y) |
237 | end | 237 | end |
238 | local _max_1 = 3 | 238 | for _index_0 = 1, 3 do |
239 | for _index_0 = 1, _max_1 < 0 and #x + _max_1 or _max_1 do | ||
240 | local y = x[_index_0] | 239 | local y = x[_index_0] |
241 | print(y) | 240 | print(y) |
242 | end | 241 | end |
243 | for _index_0 = 2, #x do | 242 | local _max_1 = #x |
243 | for _index_0 = 2, _max_1 do | ||
244 | local y = x[_index_0] | 244 | local y = x[_index_0] |
245 | print(y) | 245 | print(y) |
246 | end | 246 | end |
247 | for _index_0 = 1, #x, 2 do | 247 | local _max_2 = #x |
248 | for _index_0 = 1, _max_2, 2 do | ||
248 | local y = x[_index_0] | 249 | local y = x[_index_0] |
249 | print(y) | 250 | print(y) |
250 | end | 251 | end |
251 | for _index_0 = 2, #x, 2 do | 252 | local _max_3 = #x |
253 | for _index_0 = 2, _max_3, 2 do | ||
252 | local y = x[_index_0] | 254 | local y = x[_index_0] |
253 | print(y) | 255 | print(y) |
254 | end | 256 | end |
255 | local a, b, c = 1, 5, 2 | 257 | local a, b, c = 1, 5, 2 |
256 | local _max_2 = b | 258 | local _min_0 = a |
257 | for _index_0 = a, _max_2 < 0 and #x + _max_2 or _max_2, c do | 259 | local _max_4 = b |
260 | _min_0 = _min_0 < 0 and #x + _min_0 + 1 or _min_0 | ||
261 | _max_4 = _max_4 < 0 and #x + _max_4 + 1 or _max_4 | ||
262 | for _index_0 = _min_0, _max_4, c do | ||
258 | local y = x[_index_0] | 263 | local y = x[_index_0] |
259 | print(y) | 264 | print(y) |
260 | end | 265 | end |
@@ -287,7 +292,10 @@ do | |||
287 | a | 292 | a |
288 | }) | 293 | }) |
289 | local _list_0 = f | 294 | local _list_0 = f |
290 | for _index_0 = a, #_list_0 do | 295 | local _min_1 = a |
296 | local _max_5 = #_list_0 | ||
297 | _min_1 = _min_1 < 0 and #_list_0 + _min_1 + 1 or _min_1 | ||
298 | for _index_0 = _min_1, _max_5 do | ||
291 | local v = _list_0[_index_0] | 299 | local v = _list_0[_index_0] |
292 | print(v) | 300 | print(v) |
293 | end | 301 | end |
@@ -327,4 +335,191 @@ do | |||
327 | job = "jobless" | 335 | job = "jobless" |
328 | end | 336 | end |
329 | end | 337 | end |
338 | do | ||
339 | local transactions = { | ||
340 | "T001", | ||
341 | "T002", | ||
342 | "T003", | ||
343 | "T004", | ||
344 | "T005" | ||
345 | } | ||
346 | local middleTransactions | ||
347 | do | ||
348 | local _accum_0 = { } | ||
349 | local _len_0 = 1 | ||
350 | local _max_5 = #transactions + -2 + 1 | ||
351 | for _index_0 = 2, _max_5 do | ||
352 | local _item_0 = transactions[_index_0] | ||
353 | _accum_0[_len_0] = _item_0 | ||
354 | _len_0 = _len_0 + 1 | ||
355 | end | ||
356 | middleTransactions = _accum_0 | ||
357 | end | ||
358 | print(middleTransactions) | ||
359 | end | ||
360 | do | ||
361 | local logs = { | ||
362 | { | ||
363 | start = 0, | ||
364 | ["end"] = 100 | ||
365 | }, | ||
366 | { | ||
367 | start = 100, | ||
368 | ["end"] = 200 | ||
369 | }, | ||
370 | { | ||
371 | start = 200, | ||
372 | ["end"] = 123 | ||
373 | } | ||
374 | } | ||
375 | print(logs[#logs]["end"]) | ||
376 | end | ||
377 | do | ||
378 | local pendingOrders = { | ||
379 | "O001", | ||
380 | "O002", | ||
381 | "O003", | ||
382 | "O004" | ||
383 | } | ||
384 | print(pendingOrders[#pendingOrders - 1]) | ||
385 | end | ||
386 | do | ||
387 | local getOrders | ||
388 | getOrders = function() | ||
389 | return { | ||
390 | { | ||
391 | id = "O1001", | ||
392 | status = "pending" | ||
393 | }, | ||
394 | { | ||
395 | id = "O1002", | ||
396 | status = "processing" | ||
397 | }, | ||
398 | { | ||
399 | id = "O1003", | ||
400 | status = "done" | ||
401 | } | ||
402 | } | ||
403 | end | ||
404 | local lastStatus | ||
405 | do | ||
406 | local _item_0 = getOrders() | ||
407 | lastStatus = _item_0[#_item_0].status | ||
408 | end | ||
409 | assert(lastStatus == "done") | ||
410 | end | ||
411 | do | ||
412 | local cloneList1 | ||
413 | cloneList1 = function(list) | ||
414 | local _accum_0 = { } | ||
415 | local _len_0 = 1 | ||
416 | local _max_5 = #list | ||
417 | for _index_0 = 1, _max_5 do | ||
418 | local _item_0 = list[_index_0] | ||
419 | _accum_0[_len_0] = _item_0 | ||
420 | _len_0 = _len_0 + 1 | ||
421 | end | ||
422 | return _accum_0 | ||
423 | end | ||
424 | local cloneList2 | ||
425 | cloneList2 = function(list) | ||
426 | local _tab_0 = { } | ||
427 | local _idx_0 = #_tab_0 + 1 | ||
428 | for _index_0 = 1, #list do | ||
429 | local _value_0 = list[_index_0] | ||
430 | _tab_0[_idx_0] = _value_0 | ||
431 | _idx_0 = _idx_0 + 1 | ||
432 | end | ||
433 | return _tab_0 | ||
434 | end | ||
435 | local cloneTable | ||
436 | cloneTable = function(tb) | ||
437 | local _tab_0 = { } | ||
438 | local _idx_0 = 1 | ||
439 | for _key_0, _value_0 in pairs(tb) do | ||
440 | if _idx_0 == _key_0 then | ||
441 | _tab_0[#_tab_0 + 1] = _value_0 | ||
442 | _idx_0 = _idx_0 + 1 | ||
443 | else | ||
444 | _tab_0[_key_0] = _value_0 | ||
445 | end | ||
446 | end | ||
447 | return _tab_0 | ||
448 | end | ||
449 | end | ||
450 | do | ||
451 | print((function() | ||
452 | local _item_0 = globalTB | ||
453 | return _item_0[#_item_0] | ||
454 | end)(), (function() | ||
455 | local _item_0 = a.b.c | ||
456 | return _item_0[#_item_0 - 2] | ||
457 | end)(), (function() | ||
458 | if x ~= nil then | ||
459 | local _obj_0 = x.y | ||
460 | if _obj_0 ~= nil then | ||
461 | local _obj_1 = _obj_0(x).z | ||
462 | if _obj_1 ~= nil then | ||
463 | return _obj_1[#_obj_1 - 3] | ||
464 | end | ||
465 | return nil | ||
466 | end | ||
467 | return nil | ||
468 | end | ||
469 | return nil | ||
470 | end)()) | ||
471 | end | ||
472 | local _anon_func_0 = function(globalTB) | ||
473 | local _item_0 = globalTB | ||
474 | local _call_0 = _item_0[#_item_0] | ||
475 | return _call_0["end"](_call_0, 123) | ||
476 | end | ||
477 | local _anon_func_1 = function(a) | ||
478 | local _item_0 | ||
479 | do | ||
480 | local _accum_0 = { } | ||
481 | local _len_0 = 1 | ||
482 | local _list_0 = a.b.c | ||
483 | local _max_5 = #_list_0 + -5 + 1 | ||
484 | for _index_0 = 5, _max_5 do | ||
485 | local _item_1 = _list_0[_index_0] | ||
486 | _accum_0[_len_0] = _item_1 | ||
487 | _len_0 = _len_0 + 1 | ||
488 | end | ||
489 | _item_0 = _accum_0 | ||
490 | end | ||
491 | return _item_0[#_item_0 - 2] | ||
492 | end | ||
493 | local _anon_func_2 = function(x) | ||
494 | if x ~= nil then | ||
495 | local _obj_0 = x.y | ||
496 | if _obj_0 ~= nil then | ||
497 | local _obj_1 = _obj_0(x).z | ||
498 | if _obj_1 ~= nil then | ||
499 | local _obj_2 = _obj_1[#_obj_1 - 3] | ||
500 | if _obj_2 ~= nil then | ||
501 | local _accum_0 = { } | ||
502 | local _len_0 = 1 | ||
503 | local _max_5 = #_obj_2 + -3 + 1 | ||
504 | for _index_0 = 1, _max_5 do | ||
505 | local _item_0 = _obj_2[_index_0] | ||
506 | _accum_0[_len_0] = _item_0 | ||
507 | _len_0 = _len_0 + 1 | ||
508 | end | ||
509 | return _accum_0 | ||
510 | end | ||
511 | return nil | ||
512 | end | ||
513 | return nil | ||
514 | end | ||
515 | return nil | ||
516 | end | ||
517 | return nil | ||
518 | end | ||
519 | do | ||
520 | local f | ||
521 | f = function() | ||
522 | return print(_anon_func_0(globalTB), _anon_func_1(a), _anon_func_2(x)) | ||
523 | end | ||
524 | end | ||
330 | return nil | 525 | return nil |
diff --git a/spec/outputs/loops.lua b/spec/outputs/loops.lua index 8624d49..6ab4bbb 100644 --- a/spec/outputs/loops.lua +++ b/spec/outputs/loops.lua | |||
@@ -60,8 +60,8 @@ do | |||
60 | local y = hello[_index_0] | 60 | local y = hello[_index_0] |
61 | if y % 2 == 0 then | 61 | if y % 2 == 0 then |
62 | _accum_0[_len_0] = y | 62 | _accum_0[_len_0] = y |
63 | _len_0 = _len_0 + 1 | ||
63 | end | 64 | end |
64 | _len_0 = _len_0 + 1 | ||
65 | end | 65 | end |
66 | x = _accum_0 | 66 | x = _accum_0 |
67 | end | 67 | end |
@@ -132,13 +132,11 @@ do | |||
132 | end | 132 | end |
133 | do | 133 | do |
134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
135 | local _len_0 = 1 | ||
136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
138 | local thing = _list_2[_index_0] | 137 | local thing = _list_2[_index_0] |
139 | y = "hello" | 138 | y = "hello" |
140 | break | 139 | break |
141 | _len_0 = _len_0 + 1 | ||
142 | end | 140 | end |
143 | x = _accum_0 | 141 | x = _accum_0 |
144 | end | 142 | end |
@@ -370,3 +368,131 @@ do | |||
370 | end | 368 | end |
371 | until false | 369 | until false |
372 | end | 370 | end |
371 | local _anon_func_0 = function(i, tb) | ||
372 | local _accum_0 = { } | ||
373 | local _len_0 = 1 | ||
374 | while tb[i] do | ||
375 | i = i + 1 | ||
376 | _accum_0[_len_0] = i - 1 | ||
377 | _len_0 = _len_0 + 1 | ||
378 | end | ||
379 | return _accum_0 | ||
380 | end | ||
381 | do | ||
382 | local index | ||
383 | do | ||
384 | local _accum_0 | ||
385 | for i = 1, #tb do | ||
386 | if tb[i] then | ||
387 | _accum_0 = i | ||
388 | break | ||
389 | end | ||
390 | end | ||
391 | index = _accum_0 | ||
392 | end | ||
393 | f((function() | ||
394 | local _accum_0 | ||
395 | for i = 1, #tb do | ||
396 | if tb[i] then | ||
397 | _accum_0 = i | ||
398 | break | ||
399 | end | ||
400 | end | ||
401 | return _accum_0 | ||
402 | end)()) | ||
403 | f((function() | ||
404 | local _accum_0 = { } | ||
405 | local _len_0 = 1 | ||
406 | for i = 1, #tb do | ||
407 | if tb[i] then | ||
408 | _accum_0[_len_0] = i | ||
409 | _len_0 = _len_0 + 1 | ||
410 | end | ||
411 | end | ||
412 | return _accum_0 | ||
413 | end)()) | ||
414 | i = 1 | ||
415 | local ids | ||
416 | do | ||
417 | local _accum_0 = { } | ||
418 | local _len_0 = 1 | ||
419 | while tb[i] do | ||
420 | i = i + 1 | ||
421 | _accum_0[_len_0] = i - 1 | ||
422 | _len_0 = _len_0 + 1 | ||
423 | end | ||
424 | ids = _accum_0 | ||
425 | end | ||
426 | i = 1 | ||
427 | local idx | ||
428 | do | ||
429 | local _accum_0 | ||
430 | while tb[i] do | ||
431 | i = i + 1 | ||
432 | _accum_0 = i - 1 | ||
433 | break | ||
434 | end | ||
435 | idx = _accum_0 | ||
436 | end | ||
437 | local f1 | ||
438 | f1 = function() | ||
439 | i = 1 | ||
440 | return f(_anon_func_0(i, tb)) | ||
441 | end | ||
442 | i = 1 | ||
443 | f((function() | ||
444 | local _accum_0 | ||
445 | while tb[i] do | ||
446 | i = i + 1 | ||
447 | _accum_0 = i - 1 | ||
448 | break | ||
449 | end | ||
450 | return _accum_0 | ||
451 | end)()) | ||
452 | local _accum_0 = { } | ||
453 | local _len_0 = 1 | ||
454 | local _list_3 = items | ||
455 | for _index_0 = 1, #_list_3 do | ||
456 | local item = _list_3[_index_0] | ||
457 | local _type_0 = type(item) | ||
458 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
459 | if _tab_0 then | ||
460 | local value = item.value | ||
461 | if "A" == item.type and value ~= nil then | ||
462 | if value > 5 then | ||
463 | _accum_0[_len_0] = item | ||
464 | _len_0 = _len_0 + 1 | ||
465 | end | ||
466 | end | ||
467 | end | ||
468 | end | ||
469 | list = _accum_0 | ||
470 | end | ||
471 | do | ||
472 | repeat | ||
473 | print(1) | ||
474 | until true | ||
475 | do | ||
476 | local _accum_0 | ||
477 | repeat | ||
478 | a = func() | ||
479 | _accum_0 = a.x | ||
480 | break | ||
481 | until a.v | ||
482 | x = _accum_0 | ||
483 | end | ||
484 | local items | ||
485 | local _accum_0 = { } | ||
486 | local _len_0 = 1 | ||
487 | repeat | ||
488 | local item = getItem() | ||
489 | if not item then | ||
490 | break | ||
491 | end | ||
492 | if item.value > 0 then | ||
493 | _accum_0[_len_0] = item | ||
494 | _len_0 = _len_0 + 1 | ||
495 | end | ||
496 | until false | ||
497 | items = _accum_0 | ||
498 | end | ||
diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua index 4d31574..89c6e63 100644 --- a/spec/outputs/macro.lua +++ b/spec/outputs/macro.lua | |||
@@ -26,6 +26,10 @@ print({ | |||
26 | 123, | 26 | 123, |
27 | 'xyz' | 27 | 'xyz' |
28 | }) | 28 | }) |
29 | print({ | ||
30 | 456, | ||
31 | 'abc' | ||
32 | }) | ||
29 | do | 33 | do |
30 | assert(item == nil) | 34 | assert(item == nil) |
31 | end | 35 | end |
@@ -213,6 +217,13 @@ function tb:func() | |||
213 | end | 217 | end |
214 | end | 218 | end |
215 | print(x) | 219 | print(x) |
220 | local yue = require("yue") | ||
221 | do | ||
222 | local function f2(a) | ||
223 | return a + 1 | ||
224 | end | ||
225 | x = x + f2(3) | ||
226 | end | ||
216 | local sel | 227 | local sel |
217 | sel = function(a, b, c) | 228 | sel = function(a, b, c) |
218 | if a then | 229 | if a then |
@@ -317,7 +328,7 @@ print((setmetatable({ | |||
317 | return 998 | 328 | return 998 |
318 | end | 329 | end |
319 | })) | 330 | })) |
320 | print("current line: " .. tostring(323)) | 331 | print("current line: " .. tostring(349)) |
321 | do | 332 | do |
322 | do | 333 | do |
323 | -- TODO | 334 | -- TODO |
@@ -330,10 +341,8 @@ local _1 | |||
330 | _1 = function() | 341 | _1 = function() |
331 | print(1) | 342 | print(1) |
332 | local _accum_0 = { } | 343 | local _accum_0 = { } |
333 | local _len_0 = 1 | ||
334 | while false do | 344 | while false do |
335 | break | 345 | break |
336 | _len_0 = _len_0 + 1 | ||
337 | end | 346 | end |
338 | return _accum_0 | 347 | return _accum_0 |
339 | end | 348 | end |
diff --git a/spec/outputs/props.lua b/spec/outputs/props.lua new file mode 100644 index 0000000..2c282e0 --- /dev/null +++ b/spec/outputs/props.lua | |||
@@ -0,0 +1,240 @@ | |||
1 | local Props | ||
2 | do | ||
3 | local _class_0 | ||
4 | local assignReadOnly | ||
5 | local _base_0 = { | ||
6 | __index = function(self, name) | ||
7 | local cls = getmetatable(self) | ||
8 | do | ||
9 | local item | ||
10 | do | ||
11 | local _obj_0 = cls.__getter | ||
12 | if _obj_0 ~= nil then | ||
13 | item = _obj_0[name] | ||
14 | end | ||
15 | end | ||
16 | if item then | ||
17 | return item(self) | ||
18 | else | ||
19 | item = rawget(cls, name) | ||
20 | if item then | ||
21 | return item | ||
22 | else | ||
23 | local c = cls | ||
24 | repeat | ||
25 | c = getmetatable(c) | ||
26 | if c then | ||
27 | local _obj_0 = c.__getter | ||
28 | if _obj_0 ~= nil then | ||
29 | item = _obj_0[name] | ||
30 | end | ||
31 | if item then | ||
32 | if cls.__getter == nil then | ||
33 | cls.__getter = { } | ||
34 | end | ||
35 | cls.__getter[name] = item | ||
36 | return item(self) | ||
37 | else | ||
38 | item = rawget(c, name) | ||
39 | if item then | ||
40 | rawset(cls, name, item) | ||
41 | return item | ||
42 | end | ||
43 | end | ||
44 | else | ||
45 | break | ||
46 | end | ||
47 | until false | ||
48 | end | ||
49 | end | ||
50 | end | ||
51 | return nil | ||
52 | end, | ||
53 | __newindex = function(self, name, value) | ||
54 | local cls = getmetatable(self) | ||
55 | local item | ||
56 | local _obj_0 = cls.__setter | ||
57 | if _obj_0 ~= nil then | ||
58 | item = _obj_0[name] | ||
59 | end | ||
60 | if item then | ||
61 | return item(self, value) | ||
62 | else | ||
63 | local c = cls | ||
64 | repeat | ||
65 | c = getmetatable(c) | ||
66 | if c then | ||
67 | local _obj_1 = c.__setter | ||
68 | if _obj_1 ~= nil then | ||
69 | item = _obj_1[name] | ||
70 | end | ||
71 | if item then | ||
72 | if cls.__setter == nil then | ||
73 | cls.__setter = { } | ||
74 | end | ||
75 | cls.__setter[name] = item | ||
76 | item(self, value) | ||
77 | return | ||
78 | end | ||
79 | else | ||
80 | break | ||
81 | end | ||
82 | until false | ||
83 | return rawset(self, name, value) | ||
84 | end | ||
85 | end, | ||
86 | prop = function(self, name, props) | ||
87 | local get, set = props.get, props.set | ||
88 | if set == nil then | ||
89 | set = assignReadOnly | ||
90 | end | ||
91 | do | ||
92 | local getter = rawget(self.__base, "__getter") | ||
93 | if getter then | ||
94 | getter[name] = get | ||
95 | else | ||
96 | rawset(self.__base, "__getter", { | ||
97 | [name] = get | ||
98 | }) | ||
99 | end | ||
100 | end | ||
101 | local setter = rawget(self.__base, "__setter") | ||
102 | if setter then | ||
103 | setter[name] = set | ||
104 | else | ||
105 | return rawset(self.__base, "__setter", { | ||
106 | [name] = set | ||
107 | }) | ||
108 | end | ||
109 | end | ||
110 | } | ||
111 | if _base_0.__index == nil then | ||
112 | _base_0.__index = _base_0 | ||
113 | end | ||
114 | _class_0 = setmetatable({ | ||
115 | __init = function() end, | ||
116 | __base = _base_0, | ||
117 | __name = "Props" | ||
118 | }, { | ||
119 | __index = _base_0, | ||
120 | __call = function(cls, ...) | ||
121 | local _self_0 = setmetatable({ }, _base_0) | ||
122 | cls.__init(_self_0, ...) | ||
123 | return _self_0 | ||
124 | end | ||
125 | }) | ||
126 | _base_0.__class = _class_0 | ||
127 | local self = _class_0; | ||
128 | assignReadOnly = function() | ||
129 | return error("assigning a readonly property") | ||
130 | end | ||
131 | Props = _class_0 | ||
132 | end | ||
133 | local A | ||
134 | do | ||
135 | local _class_0 | ||
136 | local _parent_0 = Props | ||
137 | local _base_0 = { } | ||
138 | for _key_0, _val_0 in pairs(_parent_0.__base) do | ||
139 | if _base_0[_key_0] == nil and _key_0:match("^__") and not (_key_0 == "__index" and _val_0 == _parent_0.__base) then | ||
140 | _base_0[_key_0] = _val_0 | ||
141 | end | ||
142 | end | ||
143 | if _base_0.__index == nil then | ||
144 | _base_0.__index = _base_0 | ||
145 | end | ||
146 | setmetatable(_base_0, _parent_0.__base) | ||
147 | _class_0 = setmetatable({ | ||
148 | __init = function(self) | ||
149 | self._x = 0 | ||
150 | end, | ||
151 | __base = _base_0, | ||
152 | __name = "A", | ||
153 | __parent = _parent_0 | ||
154 | }, { | ||
155 | __index = function(cls, name) | ||
156 | local val = rawget(_base_0, name) | ||
157 | if val == nil then | ||
158 | local parent = rawget(cls, "__parent") | ||
159 | if parent then | ||
160 | return parent[name] | ||
161 | end | ||
162 | else | ||
163 | return val | ||
164 | end | ||
165 | end, | ||
166 | __call = function(cls, ...) | ||
167 | local _self_0 = setmetatable({ }, _base_0) | ||
168 | cls.__init(_self_0, ...) | ||
169 | return _self_0 | ||
170 | end | ||
171 | }) | ||
172 | _base_0.__class = _class_0 | ||
173 | local self = _class_0; | ||
174 | self:prop('x', { | ||
175 | get = function(self) | ||
176 | return self._x + 1000 | ||
177 | end, | ||
178 | set = function(self, v) | ||
179 | self._x = v | ||
180 | end | ||
181 | }) | ||
182 | if _parent_0.__inherited then | ||
183 | _parent_0.__inherited(_parent_0, _class_0) | ||
184 | end | ||
185 | A = _class_0 | ||
186 | end | ||
187 | local B | ||
188 | do | ||
189 | local _class_0 | ||
190 | local _parent_0 = A | ||
191 | local _base_0 = { } | ||
192 | for _key_0, _val_0 in pairs(_parent_0.__base) do | ||
193 | if _base_0[_key_0] == nil and _key_0:match("^__") and not (_key_0 == "__index" and _val_0 == _parent_0.__base) then | ||
194 | _base_0[_key_0] = _val_0 | ||
195 | end | ||
196 | end | ||
197 | if _base_0.__index == nil then | ||
198 | _base_0.__index = _base_0 | ||
199 | end | ||
200 | setmetatable(_base_0, _parent_0.__base) | ||
201 | _class_0 = setmetatable({ | ||
202 | __init = function(self, ...) | ||
203 | return _class_0.__parent.__init(self, ...) | ||
204 | end, | ||
205 | __base = _base_0, | ||
206 | __name = "B", | ||
207 | __parent = _parent_0 | ||
208 | }, { | ||
209 | __index = function(cls, name) | ||
210 | local val = rawget(_base_0, name) | ||
211 | if val == nil then | ||
212 | local parent = rawget(cls, "__parent") | ||
213 | if parent then | ||
214 | return parent[name] | ||
215 | end | ||
216 | else | ||
217 | return val | ||
218 | end | ||
219 | end, | ||
220 | __call = function(cls, ...) | ||
221 | local _self_0 = setmetatable({ }, _base_0) | ||
222 | cls.__init(_self_0, ...) | ||
223 | return _self_0 | ||
224 | end | ||
225 | }) | ||
226 | _base_0.__class = _class_0 | ||
227 | local self = _class_0; | ||
228 | self:prop('abc', { | ||
229 | get = function(self) | ||
230 | return "hello" | ||
231 | end | ||
232 | }) | ||
233 | if _parent_0.__inherited then | ||
234 | _parent_0.__inherited(_parent_0, _class_0) | ||
235 | end | ||
236 | B = _class_0 | ||
237 | end | ||
238 | local b = B() | ||
239 | b.x = 999 | ||
240 | return print(b.x, b.abc) | ||
diff --git a/spec/outputs/string.lua b/spec/outputs/string.lua index febea62..b536e6d 100644 --- a/spec/outputs/string.lua +++ b/spec/outputs/string.lua | |||
@@ -1,3 +1,4 @@ | |||
1 | local _module_0 = { } | ||
1 | local hi = "hello" | 2 | local hi = "hello" |
2 | local hello = "what the heckyes" | 3 | local hello = "what the heckyes" |
3 | print(hi) | 4 | print(hi) |
@@ -41,4 +42,42 @@ local _ = "hello"; | |||
41 | ("hello"):format().hello(1, 2, 3); | 42 | ("hello"):format().hello(1, 2, 3); |
42 | ("hello"):format(1, 2, 3) | 43 | ("hello"):format(1, 2, 3) |
43 | something("hello"):world() | 44 | something("hello"):world() |
44 | return something(("hello"):world()) | 45 | something(("hello"):world()) |
46 | do | ||
47 | local str = "key: value" | ||
48 | str = "config:\n\tenabled: true\n\tlevel: 5" | ||
49 | str = "header: start\nfooter: end" | ||
50 | str = "name: " .. tostring(username) | ||
51 | str = "count: " .. tostring(total) .. " items" | ||
52 | str = "user: " .. tostring(name) .. "\nid: " .. tostring(id) | ||
53 | str = "path: \"C:\\\\Program Files\\\\App\"\ndesc: 'single \"quote\" test'" | ||
54 | str = "key: value \nnext: 123 " | ||
55 | str = "list:\n - \"one\"\n - \"two\"" | ||
56 | str = "-- comment\ncontent text\n-- comment" | ||
57 | str = tostring(1 + 2) .. '\n' .. tostring(2 + 3) .. '\n' .. tostring("a" .. "b") | ||
58 | local obj = { | ||
59 | settings = "mode: " .. tostring(mode) .. "\nflags:\n\t- " .. tostring(flag1) .. "\n\t- default" | ||
60 | } | ||
61 | local fn | ||
62 | fn = function() | ||
63 | return "Hello\nname: " .. tostring(userName) | ||
64 | end | ||
65 | str = "result:\n\tstatus: " .. tostring((function() | ||
66 | if ok then | ||
67 | return "pass" | ||
68 | else | ||
69 | return "fail" | ||
70 | end | ||
71 | end)()) .. "\n\tcode: " .. tostring(code) | ||
72 | local summary = "date: " .. tostring(os.date()) .. "\nvalues:\n\t-\n\t\ta: " .. tostring(aVal) .. "\n\t\tb: " .. tostring(bVal or defaultB) | ||
73 | local msg = send("Hello, " .. tostring(user) .. "!\nToday is " .. tostring(os.date("%A")) .. ".") | ||
74 | local desc | ||
75 | do | ||
76 | local prefix = "Result" | ||
77 | desc = tostring(prefix) .. ":\nvalue: " .. tostring(compute()) | ||
78 | end | ||
79 | print(("1\n2\n3")) | ||
80 | end | ||
81 | local yaml = "version: " .. tostring(ver) .. "\nok: true" | ||
82 | _module_0["yaml"] = yaml | ||
83 | return _module_0 | ||
diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua index e4dedc9..7c1004b 100644 --- a/spec/outputs/switch.lua +++ b/spec/outputs/switch.lua | |||
@@ -415,4 +415,366 @@ do | |||
415 | end | 415 | end |
416 | end | 416 | end |
417 | end | 417 | end |
418 | do | ||
419 | local _exp_0 = tb | ||
420 | local _type_0 = type(_exp_0) | ||
421 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
422 | local _match_0 = false | ||
423 | if _tab_0 then | ||
424 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
425 | _match_0 = true | ||
426 | print("1, 2, 3") | ||
427 | end | ||
428 | end | ||
429 | if not _match_0 then | ||
430 | local _match_1 = false | ||
431 | if _tab_0 then | ||
432 | local b = _exp_0[2] | ||
433 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
434 | _match_1 = true | ||
435 | print("1, " .. tostring(b) .. ", 3") | ||
436 | end | ||
437 | end | ||
438 | if not _match_1 then | ||
439 | if _tab_0 then | ||
440 | local b = _exp_0[3] | ||
441 | if b == nil then | ||
442 | b = 3 | ||
443 | end | ||
444 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
445 | print("1, 2, " .. tostring(b)) | ||
446 | end | ||
447 | end | ||
448 | end | ||
449 | end | ||
450 | end | ||
451 | do | ||
452 | local _exp_0 = tb | ||
453 | local _type_0 = type(_exp_0) | ||
454 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
455 | local _match_0 = false | ||
456 | if _tab_0 then | ||
457 | local result = _exp_0.result | ||
458 | if true == _exp_0.success and result ~= nil then | ||
459 | _match_0 = true | ||
460 | print("success", result) | ||
461 | end | ||
462 | end | ||
463 | if not _match_0 then | ||
464 | local _match_1 = false | ||
465 | if _tab_0 then | ||
466 | if false == _exp_0.success then | ||
467 | _match_1 = true | ||
468 | print("failed", result) | ||
469 | end | ||
470 | end | ||
471 | if not _match_1 then | ||
472 | print("invalid") | ||
473 | end | ||
474 | end | ||
475 | end | ||
476 | do | ||
477 | local _exp_0 = tb | ||
478 | local _type_0 = type(_exp_0) | ||
479 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
480 | local _match_0 = false | ||
481 | if _tab_0 then | ||
482 | local content = _exp_0.content | ||
483 | if "success" == _exp_0.type and content ~= nil then | ||
484 | _match_0 = true | ||
485 | print("success", content) | ||
486 | end | ||
487 | end | ||
488 | if not _match_0 then | ||
489 | local _match_1 = false | ||
490 | if _tab_0 then | ||
491 | local content = _exp_0.content | ||
492 | if "error" == _exp_0.type and content ~= nil then | ||
493 | _match_1 = true | ||
494 | print("failed", content) | ||
495 | end | ||
496 | end | ||
497 | if not _match_1 then | ||
498 | print("invalid") | ||
499 | end | ||
500 | end | ||
501 | end | ||
502 | do | ||
503 | do | ||
504 | local _exp_0 = tb | ||
505 | local _type_0 = type(_exp_0) | ||
506 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
507 | if _tab_0 then | ||
508 | local fourth = _exp_0[4] | ||
509 | local _val_0 | ||
510 | do | ||
511 | local _obj_0 = _exp_0[1] | ||
512 | if _obj_0 ~= nil then | ||
513 | _val_0 = _obj_0.a | ||
514 | end | ||
515 | end | ||
516 | local _val_1 | ||
517 | do | ||
518 | local _obj_0 = _exp_0[1] | ||
519 | if _obj_0 ~= nil then | ||
520 | _val_1 = _obj_0.b | ||
521 | end | ||
522 | end | ||
523 | local _val_2 | ||
524 | do | ||
525 | local _obj_0 = _exp_0[2] | ||
526 | if _obj_0 ~= nil then | ||
527 | _val_2 = _obj_0.a | ||
528 | end | ||
529 | end | ||
530 | local _val_3 | ||
531 | do | ||
532 | local _obj_0 = _exp_0[2] | ||
533 | if _obj_0 ~= nil then | ||
534 | _val_3 = _obj_0.b | ||
535 | end | ||
536 | end | ||
537 | local _val_4 | ||
538 | do | ||
539 | local _obj_0 = _exp_0[3] | ||
540 | if _obj_0 ~= nil then | ||
541 | _val_4 = _obj_0.a | ||
542 | end | ||
543 | end | ||
544 | local _val_5 | ||
545 | do | ||
546 | local _obj_0 = _exp_0[3] | ||
547 | if _obj_0 ~= nil then | ||
548 | _val_5 = _obj_0.b | ||
549 | end | ||
550 | end | ||
551 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
552 | print("matched", fourth) | ||
553 | end | ||
554 | end | ||
555 | end | ||
556 | local _exp_0 = tb | ||
557 | local _type_0 = type(_exp_0) | ||
558 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
559 | local _match_0 = false | ||
560 | if _tab_0 then | ||
561 | local _val_0 | ||
562 | do | ||
563 | local _obj_0 = _exp_0[1] | ||
564 | if _obj_0 ~= nil then | ||
565 | _val_0 = _obj_0.c | ||
566 | end | ||
567 | end | ||
568 | local _val_1 | ||
569 | do | ||
570 | local _obj_0 = _exp_0[1] | ||
571 | if _obj_0 ~= nil then | ||
572 | _val_1 = _obj_0.d | ||
573 | end | ||
574 | end | ||
575 | local _val_2 | ||
576 | do | ||
577 | local _obj_0 = _exp_0[2] | ||
578 | if _obj_0 ~= nil then | ||
579 | _val_2 = _obj_0.c | ||
580 | end | ||
581 | end | ||
582 | local _val_3 | ||
583 | do | ||
584 | local _obj_0 = _exp_0[2] | ||
585 | if _obj_0 ~= nil then | ||
586 | _val_3 = _obj_0.d | ||
587 | end | ||
588 | end | ||
589 | local _val_4 | ||
590 | do | ||
591 | local _obj_0 = _exp_0[3] | ||
592 | if _obj_0 ~= nil then | ||
593 | _val_4 = _obj_0.c | ||
594 | end | ||
595 | end | ||
596 | local _val_5 | ||
597 | do | ||
598 | local _obj_0 = _exp_0[3] | ||
599 | if _obj_0 ~= nil then | ||
600 | _val_5 = _obj_0.d | ||
601 | end | ||
602 | end | ||
603 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 then | ||
604 | _match_0 = true | ||
605 | print("OK") | ||
606 | end | ||
607 | end | ||
608 | if not _match_0 then | ||
609 | if _tab_0 then | ||
610 | local sixth = _exp_0[6] | ||
611 | local _val_0 | ||
612 | do | ||
613 | local _obj_0 = _exp_0[3] | ||
614 | if _obj_0 ~= nil then | ||
615 | _val_0 = _obj_0.a | ||
616 | end | ||
617 | end | ||
618 | local _val_1 | ||
619 | do | ||
620 | local _obj_0 = _exp_0[3] | ||
621 | if _obj_0 ~= nil then | ||
622 | _val_1 = _obj_0.b | ||
623 | end | ||
624 | end | ||
625 | local _val_2 | ||
626 | do | ||
627 | local _obj_0 = _exp_0[4] | ||
628 | if _obj_0 ~= nil then | ||
629 | _val_2 = _obj_0.a | ||
630 | end | ||
631 | end | ||
632 | local _val_3 | ||
633 | do | ||
634 | local _obj_0 = _exp_0[4] | ||
635 | if _obj_0 ~= nil then | ||
636 | _val_3 = _obj_0.b | ||
637 | end | ||
638 | end | ||
639 | local _val_4 | ||
640 | do | ||
641 | local _obj_0 = _exp_0[5] | ||
642 | if _obj_0 ~= nil then | ||
643 | _val_4 = _obj_0.a | ||
644 | end | ||
645 | end | ||
646 | local _val_5 | ||
647 | do | ||
648 | local _obj_0 = _exp_0[5] | ||
649 | if _obj_0 ~= nil then | ||
650 | _val_5 = _obj_0.b | ||
651 | end | ||
652 | end | ||
653 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and sixth ~= nil then | ||
654 | print("matched", sixth) | ||
655 | end | ||
656 | end | ||
657 | end | ||
658 | end | ||
659 | do | ||
660 | local v = "hello" | ||
661 | if "hello" == v then | ||
662 | print("matched hello") | ||
663 | else | ||
664 | print("not matched") | ||
665 | end | ||
666 | end | ||
667 | do | ||
668 | local f | ||
669 | f = function() | ||
670 | return "ok" | ||
671 | end | ||
672 | local val = f() | ||
673 | if "ok" == val then | ||
674 | print("it's ok") | ||
675 | end | ||
676 | end | ||
677 | do | ||
678 | local g | ||
679 | g = function() | ||
680 | return 42 | ||
681 | end | ||
682 | local result = g() | ||
683 | if 1 == result or 2 == result then | ||
684 | print("small") | ||
685 | elseif 42 == result then | ||
686 | print("life universe everything") | ||
687 | else | ||
688 | print("other " .. tostring(result)) | ||
689 | end | ||
690 | end | ||
691 | do | ||
692 | local check | ||
693 | check = function() | ||
694 | if true then | ||
695 | return "yes" | ||
696 | else | ||
697 | return "no" | ||
698 | end | ||
699 | end | ||
700 | local x = check() | ||
701 | if "yes" == x then | ||
702 | print("affirmative") | ||
703 | else | ||
704 | print("negative") | ||
705 | end | ||
706 | end | ||
707 | do | ||
708 | local t | ||
709 | t = function() | ||
710 | local tb = { | ||
711 | a = 1 | ||
712 | } | ||
713 | tb.a = 2 | ||
714 | return tb | ||
715 | end | ||
716 | local data = t() | ||
717 | local _type_0 = type(data) | ||
718 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
719 | local _match_0 = false | ||
720 | if _tab_0 then | ||
721 | if 2 == data.a then | ||
722 | _match_0 = true | ||
723 | print("matched") | ||
724 | end | ||
725 | end | ||
726 | if not _match_0 then | ||
727 | print("not matched") | ||
728 | end | ||
729 | end | ||
730 | do | ||
731 | local clientData = { | ||
732 | "Meta", | ||
733 | "CUST_1001", | ||
734 | "CHK123" | ||
735 | } | ||
736 | local _type_0 = type(clientData) | ||
737 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
738 | if _tab_0 then | ||
739 | local metadata | ||
740 | do | ||
741 | local _accum_0 = { } | ||
742 | local _len_0 = 1 | ||
743 | local _max_0 = #clientData + -3 + 1 | ||
744 | for _index_0 = 1, _max_0 do | ||
745 | local _item_0 = clientData[_index_0] | ||
746 | _accum_0[_len_0] = _item_0 | ||
747 | _len_0 = _len_0 + 1 | ||
748 | end | ||
749 | metadata = _accum_0 | ||
750 | end | ||
751 | local customerId = clientData[#clientData - 1] | ||
752 | local checksum = clientData[#clientData] | ||
753 | if customerId ~= nil and checksum ~= nil then | ||
754 | print(metadata) | ||
755 | print(customerId) | ||
756 | print(checksum) | ||
757 | end | ||
758 | end | ||
759 | end | ||
760 | do | ||
761 | local handlePath | ||
762 | handlePath = function(segments) | ||
763 | local _type_0 = type(segments) | ||
764 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
765 | if _tab_0 then | ||
766 | local resource = segments[#segments - 1] | ||
767 | local action = segments[#segments] | ||
768 | if resource ~= nil and action ~= nil then | ||
769 | print("Resource:", resource) | ||
770 | return print("Action:", action) | ||
771 | end | ||
772 | end | ||
773 | end | ||
774 | handlePath({ | ||
775 | "admin", | ||
776 | "logs", | ||
777 | "view" | ||
778 | }) | ||
779 | end | ||
418 | return nil | 780 | return nil |
diff --git a/spec/outputs/tables.lua b/spec/outputs/tables.lua index f358811..3f851de 100644 --- a/spec/outputs/tables.lua +++ b/spec/outputs/tables.lua | |||
@@ -366,6 +366,28 @@ local menus = { | |||
366 | } | 366 | } |
367 | } | 367 | } |
368 | } | 368 | } |
369 | _ = { | ||
370 | boolean = { | ||
371 | true, | ||
372 | false | ||
373 | }, | ||
374 | float = { | ||
375 | 3.14, | ||
376 | -6.8523015e+5 | ||
377 | }, | ||
378 | int = { | ||
379 | 123, | ||
380 | -685230 | ||
381 | }, | ||
382 | null = { | ||
383 | nodeName = 'node', | ||
384 | parent = nil | ||
385 | }, | ||
386 | string = { | ||
387 | 'Hello world', | ||
388 | "newline\nnewline2" | ||
389 | } | ||
390 | } | ||
369 | local tb | 391 | local tb |
370 | do | 392 | do |
371 | local _tab_0 = { } | 393 | local _tab_0 = { } |
diff --git a/spec/outputs/try_catch.lua b/spec/outputs/try_catch.lua index efd92c6..edb2341 100644 --- a/spec/outputs/try_catch.lua +++ b/spec/outputs/try_catch.lua | |||
@@ -22,6 +22,44 @@ end | |||
22 | local _anon_func_7 = function(a, b, c, tb) | 22 | local _anon_func_7 = function(a, b, c, tb) |
23 | return tb.f(a, b, c) | 23 | return tb.f(a, b, c) |
24 | end | 24 | end |
25 | local _anon_func_8 = function(_arg_0, ...) | ||
26 | local ok = _arg_0 | ||
27 | return ... | ||
28 | end | ||
29 | local _anon_func_10 = function(_arg_0, ...) | ||
30 | local _ok_0 = _arg_0 | ||
31 | if _ok_0 then | ||
32 | return ... | ||
33 | end | ||
34 | end | ||
35 | local _anon_func_9 = function(func, pcall) | ||
36 | return _anon_func_10(pcall(func)) | ||
37 | end | ||
38 | local _anon_func_12 = function(_arg_0, ...) | ||
39 | local _ok_0 = _arg_0 | ||
40 | if _ok_0 then | ||
41 | return ... | ||
42 | end | ||
43 | end | ||
44 | local _anon_func_11 = function(func, pcall) | ||
45 | return _anon_func_12(pcall(func)) | ||
46 | end | ||
47 | local _anon_func_14 = function(_arg_0, ...) | ||
48 | local _ok_0 = _arg_0 | ||
49 | if _ok_0 then | ||
50 | return ... | ||
51 | end | ||
52 | end | ||
53 | local _anon_func_15 = function(func, print) | ||
54 | print(123) | ||
55 | return func() | ||
56 | end | ||
57 | local _anon_func_13 = function(func, print, xpcall) | ||
58 | return _anon_func_14(xpcall(_anon_func_15, function(e) | ||
59 | print(e) | ||
60 | return e | ||
61 | end, func, print)) | ||
62 | end | ||
25 | local f | 63 | local f |
26 | f = function() | 64 | f = function() |
27 | xpcall(function() | 65 | xpcall(function() |
@@ -104,10 +142,236 @@ f = function() | |||
104 | do | 142 | do |
105 | x(function() | 143 | x(function() |
106 | local tb, a, b, c | 144 | local tb, a, b, c |
107 | f = function() | 145 | local f1 |
146 | f1 = function() | ||
108 | return pcall(_anon_func_7, a, b, c, tb) | 147 | return pcall(_anon_func_7, a, b, c, tb) |
109 | end | 148 | end |
110 | end) | 149 | end) |
111 | end | 150 | end |
151 | do | ||
152 | local f1 | ||
153 | f1 = function() | ||
154 | do | ||
155 | return _anon_func_8(pcall(function() | ||
156 | return func() | ||
157 | end)) | ||
158 | end | ||
159 | end | ||
160 | end | ||
161 | do | ||
162 | local func | ||
163 | local a, b, c | ||
164 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
165 | if _ok_0 then | ||
166 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
167 | end | ||
168 | end | ||
169 | do | ||
170 | local a, b, c | ||
171 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
172 | return func() | ||
173 | end) | ||
174 | if _ok_0 then | ||
175 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
176 | end | ||
177 | end | ||
178 | do | ||
179 | local a | ||
180 | local _exp_0 = (_anon_func_9(func, pcall)) | ||
181 | if _exp_0 ~= nil then | ||
182 | a = _exp_0 | ||
183 | else | ||
184 | a = "default" | ||
185 | end | ||
186 | end | ||
187 | do | ||
188 | f(_anon_func_11(func, pcall)) | ||
189 | end | ||
190 | do | ||
191 | f(_anon_func_13(func, print, xpcall)) | ||
192 | end | ||
112 | return nil | 193 | return nil |
113 | end | 194 | end |
195 | local _anon_func_16 = function(a, b, c, tb) | ||
196 | return tb.f(a, b, c) | ||
197 | end | ||
198 | local _anon_func_17 = function(_arg_0, ...) | ||
199 | local ok = _arg_0 | ||
200 | return ... | ||
201 | end | ||
202 | do | ||
203 | xpcall(function() | ||
204 | return func(1, 2, 3) | ||
205 | end, function(err) | ||
206 | return print(err) | ||
207 | end) | ||
208 | xpcall(function() | ||
209 | return func(1, 2, 3) | ||
210 | end, function(err) | ||
211 | return print(err) | ||
212 | end) | ||
213 | pcall(function() | ||
214 | print("trying") | ||
215 | return func(1, 2, 3) | ||
216 | end) | ||
217 | do | ||
218 | local success, result = xpcall(function() | ||
219 | return func(1, 2, 3) | ||
220 | end, function(err) | ||
221 | return print(err) | ||
222 | end) | ||
223 | success, result = pcall(function() | ||
224 | return func(1, 2, 3) | ||
225 | end) | ||
226 | end | ||
227 | local tb = { } | ||
228 | pcall(function() | ||
229 | return tb.func | ||
230 | end) | ||
231 | pcall(function() | ||
232 | return tb.func() | ||
233 | end) | ||
234 | pcall(function() | ||
235 | return tb.func() | ||
236 | end) | ||
237 | pcall(function() | ||
238 | return (tb.func()) | ||
239 | end) | ||
240 | pcall(function() | ||
241 | return (tb:func(1, 2, 3)) | ||
242 | end) | ||
243 | pcall(function() | ||
244 | return tb.func(1) | ||
245 | end) | ||
246 | pcall(function() | ||
247 | return tb.func(1) | ||
248 | end) | ||
249 | if (xpcall(function() | ||
250 | return func(1) | ||
251 | end, function(err) | ||
252 | return print(err) | ||
253 | end)) then | ||
254 | print("OK") | ||
255 | end | ||
256 | if xpcall(function() | ||
257 | return (func(1)) | ||
258 | end, function(err) | ||
259 | return print(err) | ||
260 | end) then | ||
261 | print("OK") | ||
262 | end | ||
263 | do | ||
264 | do | ||
265 | local success, result = pcall(function() | ||
266 | return func("abc", 123) | ||
267 | end) | ||
268 | if success then | ||
269 | print(result) | ||
270 | end | ||
271 | end | ||
272 | local success, result = xpcall(function() | ||
273 | return func("abc", 123) | ||
274 | end, function(err) | ||
275 | return print(err) | ||
276 | end) | ||
277 | success, result = xpcall(function() | ||
278 | return func("abc", 123) | ||
279 | end, function(err) | ||
280 | return print(err) | ||
281 | end) | ||
282 | if success then | ||
283 | print(result) | ||
284 | end | ||
285 | end | ||
286 | do | ||
287 | pcall(function() | ||
288 | return func(1, 2, 3) | ||
289 | end) | ||
290 | pcall(function() | ||
291 | return func(1, 2, 3) | ||
292 | end) | ||
293 | end | ||
294 | do | ||
295 | x(function() | ||
296 | local tb, a, b, c | ||
297 | local f1 | ||
298 | f1 = function() | ||
299 | return pcall(_anon_func_16, a, b, c, tb) | ||
300 | end | ||
301 | end) | ||
302 | end | ||
303 | do | ||
304 | local f1 | ||
305 | f1 = function() | ||
306 | do | ||
307 | return _anon_func_17(pcall(function() | ||
308 | return func() | ||
309 | end)) | ||
310 | end | ||
311 | end | ||
312 | end | ||
313 | do | ||
314 | local func | ||
315 | local a, b, c | ||
316 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
317 | if _ok_0 then | ||
318 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
319 | end | ||
320 | end | ||
321 | do | ||
322 | local a, b, c | ||
323 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
324 | return func() | ||
325 | end) | ||
326 | if _ok_0 then | ||
327 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
328 | end | ||
329 | end | ||
330 | do | ||
331 | local a | ||
332 | local _exp_0 = ((function() | ||
333 | return (function(_arg_0, ...) | ||
334 | local _ok_0 = _arg_0 | ||
335 | if _ok_0 then | ||
336 | return ... | ||
337 | end | ||
338 | end)(pcall(function() | ||
339 | return func() | ||
340 | end)) | ||
341 | end)()) | ||
342 | if _exp_0 ~= nil then | ||
343 | a = _exp_0 | ||
344 | else | ||
345 | a = "default" | ||
346 | end | ||
347 | end | ||
348 | do | ||
349 | f((function() | ||
350 | return (function(_arg_0, ...) | ||
351 | local _ok_0 = _arg_0 | ||
352 | if _ok_0 then | ||
353 | return ... | ||
354 | end | ||
355 | end)(pcall(function() | ||
356 | return func() | ||
357 | end)) | ||
358 | end)()) | ||
359 | end | ||
360 | do | ||
361 | f((function() | ||
362 | return (function(_arg_0, ...) | ||
363 | local _ok_0 = _arg_0 | ||
364 | if _ok_0 then | ||
365 | return ... | ||
366 | end | ||
367 | end)(xpcall(function() | ||
368 | print(123) | ||
369 | return func() | ||
370 | end, function(e) | ||
371 | print(e) | ||
372 | return e | ||
373 | end)) | ||
374 | end)()) | ||
375 | end | ||
376 | end | ||
377 | return nil | ||
diff --git a/spec/outputs/unicode/assign.lua b/spec/outputs/unicode/assign.lua index d4ad56a..e00d016 100644 --- a/spec/outputs/unicode/assign.lua +++ b/spec/outputs/unicode/assign.lua | |||
@@ -43,10 +43,8 @@ do | |||
43 | end | 43 | end |
44 | end | 44 | end |
45 | local _anon_func_0 = function(_u6253_u5370) | 45 | local _anon_func_0 = function(_u6253_u5370) |
46 | do | 46 | _u6253_u5370(123) |
47 | _u6253_u5370(123) | 47 | return { } |
48 | return { } | ||
49 | end | ||
50 | end | 48 | end |
51 | return __u65e0_u6548_u53d8_u91cf(function() | 49 | return __u65e0_u6548_u53d8_u91cf(function() |
52 | setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370)) | 50 | setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370)) |
diff --git a/spec/outputs/unicode/comprehension.lua b/spec/outputs/unicode/comprehension.lua index 60e490f..92bce69 100644 --- a/spec/outputs/unicode/comprehension.lua +++ b/spec/outputs/unicode/comprehension.lua | |||
@@ -243,8 +243,11 @@ end | |||
243 | do | 243 | do |
244 | local _accum_0 = { } | 244 | local _accum_0 = { } |
245 | local _len_0 = 1 | 245 | local _len_0 = 1 |
246 | local _min_0 = 1 + 2 | ||
246 | local _max_0 = 3 + 4 | 247 | local _max_0 = 3 + 4 |
247 | for _index_0 = 1 + 2, _max_0 < 0 and #_u5217_u8868 + _max_0 or _max_0 do | 248 | _min_0 = _min_0 < 0 and #_u5217_u8868 + _min_0 + 1 or _min_0 |
249 | _max_0 = _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 | ||
250 | for _index_0 = _min_0, _max_0 do | ||
248 | local _u9879_u76ee = _u5217_u8868[_index_0] | 251 | local _u9879_u76ee = _u5217_u8868[_index_0] |
249 | _accum_0[_len_0] = _u9879_u76ee | 252 | _accum_0[_len_0] = _u9879_u76ee |
250 | _len_0 = _len_0 + 1 | 253 | _len_0 = _len_0 + 1 |
@@ -254,8 +257,11 @@ end | |||
254 | do | 257 | do |
255 | local _accum_0 = { } | 258 | local _accum_0 = { } |
256 | local _len_0 = 1 | 259 | local _len_0 = 1 |
260 | local _min_0 = _u4f60_u597d() * 4 | ||
257 | local _max_0 = 2 - _u4e1c_u897f[4] | 261 | local _max_0 = 2 - _u4e1c_u897f[4] |
258 | for _index_0 = _u4f60_u597d() * 4, _max_0 < 0 and #_u5217_u8868 + _max_0 or _max_0 do | 262 | _min_0 = _min_0 < 0 and #_u5217_u8868 + _min_0 + 1 or _min_0 |
263 | _max_0 = _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 | ||
264 | for _index_0 = _min_0, _max_0 do | ||
259 | local _u9879_u76ee = _u5217_u8868[_index_0] | 265 | local _u9879_u76ee = _u5217_u8868[_index_0] |
260 | _accum_0[_len_0] = _u9879_u76ee | 266 | _accum_0[_len_0] = _u9879_u76ee |
261 | _len_0 = _len_0 + 1 | 267 | _len_0 = _len_0 + 1 |
diff --git a/spec/outputs/unicode/lists.lua b/spec/outputs/unicode/lists.lua index aafd516..3bf6f50 100644 --- a/spec/outputs/unicode/lists.lua +++ b/spec/outputs/unicode/lists.lua | |||
@@ -229,31 +229,36 @@ _u53d8_u91cfx = { | |||
229 | 6, | 229 | 6, |
230 | 7 | 230 | 7 |
231 | } | 231 | } |
232 | local _max_0 = -5 | 232 | local _max_0 = #_u53d8_u91cfx + -5 + 1 |
233 | for _index_0 = 2, _max_0 < 0 and #_u53d8_u91cfx + _max_0 or _max_0, 2 do | 233 | for _index_0 = 2, _max_0, 2 do |
234 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 234 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
235 | _u6253_u5370(_u53d8_u91cfy) | 235 | _u6253_u5370(_u53d8_u91cfy) |
236 | end | 236 | end |
237 | local _max_1 = 3 | 237 | for _index_0 = 1, 3 do |
238 | for _index_0 = 1, _max_1 < 0 and #_u53d8_u91cfx + _max_1 or _max_1 do | ||
239 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 238 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
240 | _u6253_u5370(_u53d8_u91cfy) | 239 | _u6253_u5370(_u53d8_u91cfy) |
241 | end | 240 | end |
242 | for _index_0 = 2, #_u53d8_u91cfx do | 241 | local _max_1 = #_u53d8_u91cfx |
242 | for _index_0 = 2, _max_1 do | ||
243 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 243 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
244 | _u6253_u5370(_u53d8_u91cfy) | 244 | _u6253_u5370(_u53d8_u91cfy) |
245 | end | 245 | end |
246 | for _index_0 = 1, #_u53d8_u91cfx, 2 do | 246 | local _max_2 = #_u53d8_u91cfx |
247 | for _index_0 = 1, _max_2, 2 do | ||
247 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 248 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
248 | _u6253_u5370(_u53d8_u91cfy) | 249 | _u6253_u5370(_u53d8_u91cfy) |
249 | end | 250 | end |
250 | for _index_0 = 2, #_u53d8_u91cfx, 2 do | 251 | local _max_3 = #_u53d8_u91cfx |
252 | for _index_0 = 2, _max_3, 2 do | ||
251 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 253 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
252 | _u6253_u5370(_u53d8_u91cfy) | 254 | _u6253_u5370(_u53d8_u91cfy) |
253 | end | 255 | end |
254 | local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2 | 256 | local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2 |
255 | local _max_2 = _u53d8_u91cfb | 257 | local _min_0 = _u53d8_u91cfa |
256 | for _index_0 = _u53d8_u91cfa, _max_2 < 0 and #_u53d8_u91cfx + _max_2 or _max_2, _u53d8_u91cfc do | 258 | local _max_4 = _u53d8_u91cfb |
259 | _min_0 = _min_0 < 0 and #_u53d8_u91cfx + _min_0 + 1 or _min_0 | ||
260 | _max_4 = _max_4 < 0 and #_u53d8_u91cfx + _max_4 + 1 or _max_4 | ||
261 | for _index_0 = _min_0, _max_4, _u53d8_u91cfc do | ||
257 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 262 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
258 | _u6253_u5370(_u53d8_u91cfy) | 263 | _u6253_u5370(_u53d8_u91cfy) |
259 | end | 264 | end |
diff --git a/spec/outputs/unicode/loops.lua b/spec/outputs/unicode/loops.lua index 8379993..27bbe2e 100644 --- a/spec/outputs/unicode/loops.lua +++ b/spec/outputs/unicode/loops.lua | |||
@@ -60,8 +60,8 @@ do | |||
60 | local _u53d8_u91cfy = _u4f60_u597d[_index_0] | 60 | local _u53d8_u91cfy = _u4f60_u597d[_index_0] |
61 | if _u53d8_u91cfy % 2 == 0 then | 61 | if _u53d8_u91cfy % 2 == 0 then |
62 | _accum_0[_len_0] = _u53d8_u91cfy | 62 | _accum_0[_len_0] = _u53d8_u91cfy |
63 | _len_0 = _len_0 + 1 | ||
63 | end | 64 | end |
64 | _len_0 = _len_0 + 1 | ||
65 | end | 65 | end |
66 | _u53d8_u91cfx = _accum_0 | 66 | _u53d8_u91cfx = _accum_0 |
67 | end | 67 | end |
@@ -132,13 +132,11 @@ do | |||
132 | end | 132 | end |
133 | do | 133 | do |
134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
135 | local _len_0 = 1 | ||
136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
138 | local _u4e1c_u897f = _list_2[_index_0] | 137 | local _u4e1c_u897f = _list_2[_index_0] |
139 | _u53d8_u91cfy = "ä½ å¥½" | 138 | _u53d8_u91cfy = "ä½ å¥½" |
140 | break | 139 | break |
141 | _len_0 = _len_0 + 1 | ||
142 | end | 140 | end |
143 | _u53d8_u91cfx = _accum_0 | 141 | _u53d8_u91cfx = _accum_0 |
144 | end | 142 | end |
diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua index b14f571..b4e78cd 100644 --- a/spec/outputs/unicode/macro.lua +++ b/spec/outputs/unicode/macro.lua | |||
@@ -216,17 +216,15 @@ do | |||
216 | end | 216 | end |
217 | local _ = require('下划线') | 217 | local _ = require('下划线') |
218 | local _anon_func_0 = function(_) | 218 | local _anon_func_0 = function(_) |
219 | do | 219 | local _call_0 = (_({ |
220 | local _call_0 = (_({ | 220 | 1, |
221 | 1, | 221 | 2, |
222 | 2, | 222 | 3, |
223 | 3, | 223 | 4, |
224 | 4, | 224 | -2, |
225 | -2, | 225 | 3 |
226 | 3 | 226 | })) |
227 | })) | 227 | return _call_0["链"](_call_0) |
228 | return _call_0["链"](_call_0) | ||
229 | end | ||
230 | end | 228 | end |
231 | local _call_0 = ((function() | 229 | local _call_0 = ((function() |
232 | local _call_0 = ((function() | 230 | local _call_0 = ((function() |
@@ -241,17 +239,15 @@ local _call_0 = ((function() | |||
241 | end)()) | 239 | end)()) |
242 | local _u7ed3_u679ca = _call_0["å–值"](_call_0) | 240 | local _u7ed3_u679ca = _call_0["å–值"](_call_0) |
243 | local _anon_func_1 = function(_) | 241 | local _anon_func_1 = function(_) |
244 | do | 242 | local _call_1 = (_({ |
245 | local _call_1 = (_({ | 243 | 1, |
246 | 1, | 244 | 2, |
247 | 2, | 245 | 3, |
248 | 3, | 246 | 4, |
249 | 4, | 247 | -2, |
250 | -2, | 248 | 3 |
251 | 3 | 249 | })) |
252 | })) | 250 | return _call_1["链"](_call_1) |
253 | return _call_1["链"](_call_1) | ||
254 | end | ||
255 | end | 251 | end |
256 | do | 252 | do |
257 | local _call_1 = ((function() | 253 | local _call_1 = ((function() |
@@ -270,10 +266,8 @@ do | |||
270 | end) | 266 | end) |
271 | end | 267 | end |
272 | local _anon_func_2 = function(_u539f_u70b9) | 268 | local _anon_func_2 = function(_u539f_u70b9) |
273 | do | 269 | local _call_1 = _u539f_u70b9["å˜æ¢"]["æ ¹èŠ‚ç‚¹"]["游æˆå¯¹è±¡"] |
274 | local _call_1 = _u539f_u70b9["å˜æ¢"]["æ ¹èŠ‚ç‚¹"]["游æˆå¯¹è±¡"] | 270 | return _call_1["父节点"](_call_1) |
275 | return _call_1["父节点"](_call_1) | ||
276 | end | ||
277 | end | 271 | end |
278 | local _call_1 = ((function() | 272 | local _call_1 = ((function() |
279 | local _call_1 = ((function() | 273 | local _call_1 = ((function() |
@@ -365,10 +359,8 @@ local _1 | |||
365 | _1 = function() | 359 | _1 = function() |
366 | _u6253_u5370(1) | 360 | _u6253_u5370(1) |
367 | local _accum_0 = { } | 361 | local _accum_0 = { } |
368 | local _len_0 = 1 | ||
369 | while false do | 362 | while false do |
370 | break | 363 | break |
371 | _len_0 = _len_0 + 1 | ||
372 | end | 364 | end |
373 | return _accum_0 | 365 | return _accum_0 |
374 | end | 366 | end |
diff --git a/spec/outputs/unicode/multiline_chain.lua b/spec/outputs/unicode/multiline_chain.lua index c1da13f..61e7057 100644 --- a/spec/outputs/unicode/multiline_chain.lua +++ b/spec/outputs/unicode/multiline_chain.lua | |||
@@ -59,10 +59,8 @@ _u51fd_u6570 = function() | |||
59 | return _accum_0 | 59 | return _accum_0 |
60 | end | 60 | end |
61 | local _anon_func_0 = function(_u53d8_u91cfa) | 61 | local _anon_func_0 = function(_u53d8_u91cfa) |
62 | do | 62 | local _call_1 = _u53d8_u91cfa |
63 | local _call_1 = _u53d8_u91cfa | 63 | return (_call_1["å˜é‡b"](_call_1, 123))["å˜é‡c"]("abc") |
64 | return (_call_1["å˜é‡b"](_call_1, 123))["å˜é‡c"]("abc") | ||
65 | end | ||
66 | end | 64 | end |
67 | local _u51fd_u65701 | 65 | local _u51fd_u65701 |
68 | _u51fd_u65701 = function() | 66 | _u51fd_u65701 = function() |
diff --git a/spec/outputs/unicode/syntax.lua b/spec/outputs/unicode/syntax.lua index 1984f40..a13302b 100644 --- a/spec/outputs/unicode/syntax.lua +++ b/spec/outputs/unicode/syntax.lua | |||
@@ -286,10 +286,8 @@ _ = 5 - _u4ec0_u4e48(_u65e0_u804a) | |||
286 | _u4ec0_u4e48(_u65e0_u804a - 5) | 286 | _u4ec0_u4e48(_u65e0_u804a - 5) |
287 | _u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269 | 287 | _u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269 |
288 | local _anon_func_0 = function(_u4ec0_u4e48) | 288 | local _anon_func_0 = function(_u4ec0_u4e48) |
289 | do | 289 | local _call_8 = _u4ec0_u4e48 |
290 | local _call_8 = _u4ec0_u4e48 | 290 | return _call_8["é…·"](_call_8, 100) |
291 | return _call_8["é…·"](_call_8, 100) | ||
292 | end | ||
293 | end | 291 | end |
294 | (function(_u67d0_u7269) | 292 | (function(_u67d0_u7269) |
295 | if _u67d0_u7269 == nil then | 293 | if _u67d0_u7269 == nil then |
diff --git a/spec/outputs/unicode/vararg.lua b/spec/outputs/unicode/vararg.lua index b837006..fc894ff 100644 --- a/spec/outputs/unicode/vararg.lua +++ b/spec/outputs/unicode/vararg.lua | |||
@@ -125,14 +125,10 @@ local _anon_func_11 = function(_u9879_u76ee, ...) | |||
125 | return _tbl_0 | 125 | return _tbl_0 |
126 | end | 126 | end |
127 | local _anon_func_12 = function(_u51fd_u6570) | 127 | local _anon_func_12 = function(_u51fd_u6570) |
128 | do | 128 | return _u51fd_u6570() |
129 | return _u51fd_u6570() | ||
130 | end | ||
131 | end | 129 | end |
132 | local _anon_func_13 = function(_u51fd_u6570, ...) | 130 | local _anon_func_13 = function(_u51fd_u6570, ...) |
133 | do | 131 | return _u51fd_u6570(...) |
134 | return _u51fd_u6570(...) | ||
135 | end | ||
136 | end | 132 | end |
137 | local _anon_func_14 = function(_u51fd_u6570) | 133 | local _anon_func_14 = function(_u51fd_u6570) |
138 | local _accum_0 = { } | 134 | local _accum_0 = { } |
@@ -195,15 +191,11 @@ local _anon_func_23 = function(_u51fd_u6570, ...) | |||
195 | return nil | 191 | return nil |
196 | end | 192 | end |
197 | local _anon_func_24 = function(_u6253_u5370, select, ...) | 193 | local _anon_func_24 = function(_u6253_u5370, select, ...) |
198 | do | 194 | _u6253_u5370(select("#", ...)) |
199 | _u6253_u5370(select("#", ...)) | 195 | return _u6253_u5370(...) |
200 | return _u6253_u5370(...) | ||
201 | end | ||
202 | end | 196 | end |
203 | local _anon_func_25 = function(_u6253_u5370, ...) | 197 | local _anon_func_25 = function(_u6253_u5370, ...) |
204 | do | 198 | return _u6253_u5370(...) |
205 | return _u6253_u5370(...) | ||
206 | end | ||
207 | end | 199 | end |
208 | local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) | 200 | local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) |
209 | if 1 == _u53d8_u91cfx then | 201 | if 1 == _u53d8_u91cfx then |
@@ -214,9 +206,7 @@ local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) | |||
214 | end | 206 | end |
215 | end | 207 | end |
216 | local _anon_func_27 = function(_u6253_u5370, ...) | 208 | local _anon_func_27 = function(_u6253_u5370, ...) |
217 | do | 209 | return _u6253_u5370(...) |
218 | return _u6253_u5370(...) | ||
219 | end | ||
220 | end | 210 | end |
221 | local _anon_func_28 = function(_u6761_u4ef6) | 211 | local _anon_func_28 = function(_u6761_u4ef6) |
222 | if _u6761_u4ef6 then | 212 | if _u6761_u4ef6 then |
@@ -224,10 +214,8 @@ local _anon_func_28 = function(_u6761_u4ef6) | |||
224 | end | 214 | end |
225 | end | 215 | end |
226 | local _anon_func_29 = function(_u6253_u5370, _arg_0, ...) | 216 | local _anon_func_29 = function(_u6253_u5370, _arg_0, ...) |
227 | do | 217 | local _u8868 = _arg_0 |
228 | local _u8868 = _arg_0 | 218 | return _u6253_u5370(...) |
229 | return _u6253_u5370(...) | ||
230 | end | ||
231 | end | 219 | end |
232 | local _u8fde_u63a5 | 220 | local _u8fde_u63a5 |
233 | _u8fde_u63a5 = function(...) | 221 | _u8fde_u63a5 = function(...) |
diff --git a/spec/outputs/upvalue_func.lua b/spec/outputs/upvalue_func.lua index 3181adf..3e088be 100644 --- a/spec/outputs/upvalue_func.lua +++ b/spec/outputs/upvalue_func.lua | |||
@@ -214,10 +214,8 @@ local _anon_func_1 = function(valueB) | |||
214 | end | 214 | end |
215 | end | 215 | end |
216 | local _anon_func_2 = function(print, select, _arg_0, ...) | 216 | local _anon_func_2 = function(print, select, _arg_0, ...) |
217 | do | 217 | local ok = _arg_0 |
218 | local ok = _arg_0 | 218 | return print(select(3, ...)) |
219 | return print(select(3, ...)) | ||
220 | end | ||
221 | end | 219 | end |
222 | local _anon_func_3 = function(tb) | 220 | local _anon_func_3 = function(tb) |
223 | if tb ~= nil then | 221 | if tb ~= nil then |
@@ -242,11 +240,9 @@ local _anon_func_5 = function(getmetatable, tb) | |||
242 | return _obj_0[1 + 1](_obj_0, "abc") | 240 | return _obj_0[1 + 1](_obj_0, "abc") |
243 | end | 241 | end |
244 | local _anon_func_6 = function(tb) | 242 | local _anon_func_6 = function(tb) |
245 | do | 243 | local _call_0 = tb |
246 | local _call_0 = tb | 244 | local _call_1 = _call_0["end"](_call_0) |
247 | local _call_1 = _call_0["end"](_call_0) | 245 | return _call_1["🤣"](_call_1, 123) |
248 | return _call_1["🤣"](_call_1, 123) | ||
249 | end | ||
250 | end | 246 | end |
251 | local _anon_func_7 = function(itemA, listA) | 247 | local _anon_func_7 = function(itemA, listA) |
252 | for _index_0 = 1, #listA do | 248 | for _index_0 = 1, #listA do |
@@ -354,17 +350,13 @@ local _anon_func_16 = function(pairs, tb, tostring) | |||
354 | return _tbl_0 | 350 | return _tbl_0 |
355 | end | 351 | end |
356 | local _anon_func_17 = function(print) | 352 | local _anon_func_17 = function(print) |
357 | do | 353 | print(123) |
358 | print(123) | 354 | return "abc" |
359 | return "abc" | ||
360 | end | ||
361 | end | 355 | end |
362 | local _anon_func_18 = function(print, select, _arg_0, ...) | 356 | local _anon_func_18 = function(print, select, _arg_0, ...) |
363 | do | 357 | local success = _arg_0 |
364 | local success = _arg_0 | 358 | if success then |
365 | if success then | 359 | return print(select('#', ...)) |
366 | return print(select('#', ...)) | ||
367 | end | ||
368 | end | 360 | end |
369 | end | 361 | end |
370 | local _anon_func_19 = function(cond, i) | 362 | local _anon_func_19 = function(cond, i) |
@@ -459,11 +451,9 @@ local _anon_func_25 = function(itemA, listA) | |||
459 | return false | 451 | return false |
460 | end | 452 | end |
461 | local _anon_func_24 = function(itemA, listA, tb) | 453 | local _anon_func_24 = function(itemA, listA, tb) |
462 | do | 454 | local _call_0 = tb |
463 | local _call_0 = tb | 455 | local _call_1 = _call_0["end"](_call_0) |
464 | local _call_1 = _call_0["end"](_call_0) | 456 | return _call_1["🤣"](_call_1, 123 and (#listA > 0 and _anon_func_25(itemA, listA))) |
465 | return _call_1["🤣"](_call_1, 123 and (#listA > 0 and _anon_func_25(itemA, listA))) | ||
466 | end | ||
467 | end | 457 | end |
468 | GameEngine:onEvent("SomeEvent", function() | 458 | GameEngine:onEvent("SomeEvent", function() |
469 | return func(value + (_anon_func_21(cond)) + (_anon_func_22(valueB)) > _anon_func_23(tb) + _anon_func_24(itemA, listA, tb)) | 459 | return func(value + (_anon_func_21(cond)) + (_anon_func_22(valueB)) > _anon_func_23(tb) + _anon_func_24(itemA, listA, tb)) |
@@ -503,13 +493,11 @@ local _anon_func_27 = function(char) | |||
503 | return nil | 493 | return nil |
504 | end | 494 | end |
505 | local _anon_func_28 = function(os, _arg_0, ...) | 495 | local _anon_func_28 = function(os, _arg_0, ...) |
506 | do | 496 | local ok = _arg_0 |
507 | local ok = _arg_0 | 497 | if ok then |
508 | if ok then | 498 | return ... |
509 | return ... | 499 | else |
510 | else | 500 | return os.exit(1) |
511 | return os.exit(1) | ||
512 | end | ||
513 | end | 501 | end |
514 | end | 502 | end |
515 | local _anon_func_29 = function(debug_env_after, debug_env_before, env, func) | 503 | local _anon_func_29 = function(debug_env_after, debug_env_before, env, func) |
diff --git a/spec/outputs/vararg.lua b/spec/outputs/vararg.lua index dabba44..254aa6a 100644 --- a/spec/outputs/vararg.lua +++ b/spec/outputs/vararg.lua | |||
@@ -125,14 +125,10 @@ local _anon_func_11 = function(items, ...) | |||
125 | return _tbl_0 | 125 | return _tbl_0 |
126 | end | 126 | end |
127 | local _anon_func_12 = function(func) | 127 | local _anon_func_12 = function(func) |
128 | do | 128 | return func() |
129 | return func() | ||
130 | end | ||
131 | end | 129 | end |
132 | local _anon_func_13 = function(func, ...) | 130 | local _anon_func_13 = function(func, ...) |
133 | do | 131 | return func(...) |
134 | return func(...) | ||
135 | end | ||
136 | end | 132 | end |
137 | local _anon_func_14 = function(func) | 133 | local _anon_func_14 = function(func) |
138 | local _accum_0 = { } | 134 | local _accum_0 = { } |
@@ -195,15 +191,11 @@ local _anon_func_23 = function(func, ...) | |||
195 | return nil | 191 | return nil |
196 | end | 192 | end |
197 | local _anon_func_24 = function(print, select, ...) | 193 | local _anon_func_24 = function(print, select, ...) |
198 | do | 194 | print(select("#", ...)) |
199 | print(select("#", ...)) | 195 | return print(...) |
200 | return print(...) | ||
201 | end | ||
202 | end | 196 | end |
203 | local _anon_func_25 = function(print, ...) | 197 | local _anon_func_25 = function(print, ...) |
204 | do | 198 | return print(...) |
205 | return print(...) | ||
206 | end | ||
207 | end | 199 | end |
208 | local _anon_func_26 = function(tb, tb2, x) | 200 | local _anon_func_26 = function(tb, tb2, x) |
209 | if 1 == x then | 201 | if 1 == x then |
@@ -214,9 +206,7 @@ local _anon_func_26 = function(tb, tb2, x) | |||
214 | end | 206 | end |
215 | end | 207 | end |
216 | local _anon_func_27 = function(print, ...) | 208 | local _anon_func_27 = function(print, ...) |
217 | do | 209 | return print(...) |
218 | return print(...) | ||
219 | end | ||
220 | end | 210 | end |
221 | local _anon_func_28 = function(cond) | 211 | local _anon_func_28 = function(cond) |
222 | if cond then | 212 | if cond then |
@@ -224,10 +214,8 @@ local _anon_func_28 = function(cond) | |||
224 | end | 214 | end |
225 | end | 215 | end |
226 | local _anon_func_29 = function(print, _arg_0, ...) | 216 | local _anon_func_29 = function(print, _arg_0, ...) |
227 | do | 217 | local tb = _arg_0 |
228 | local tb = _arg_0 | 218 | return print(...) |
229 | return print(...) | ||
230 | end | ||
231 | end | 219 | end |
232 | local join | 220 | local join |
233 | join = function(...) | 221 | join = function(...) |
diff --git a/spec/outputs/with.lua b/spec/outputs/with.lua index 1a795c1..530915e 100644 --- a/spec/outputs/with.lua +++ b/spec/outputs/with.lua | |||
@@ -187,4 +187,66 @@ do | |||
187 | return _with_0[123] | 187 | return _with_0[123] |
188 | end | 188 | end |
189 | end | 189 | end |
190 | do | ||
191 | f((function() | ||
192 | local _with_0 = item | ||
193 | do | ||
194 | local _accum_0 | ||
195 | repeat | ||
196 | if _with_0.id > 0 then | ||
197 | _accum_0 = _with_0.content | ||
198 | break | ||
199 | end | ||
200 | until true | ||
201 | _with_0 = _accum_0 | ||
202 | end | ||
203 | return _with_0 | ||
204 | end)()) | ||
205 | local a | ||
206 | do | ||
207 | local _with_0 = tb | ||
208 | do | ||
209 | local _accum_0 | ||
210 | repeat | ||
211 | if _with_0.v then | ||
212 | _accum_0 = _with_0.a | ||
213 | break | ||
214 | end | ||
215 | until true | ||
216 | _with_0 = _accum_0 | ||
217 | end | ||
218 | a = _with_0 | ||
219 | end | ||
220 | local _accum_0 | ||
221 | while true do | ||
222 | local _with_0 = tb | ||
223 | local _accum_1 | ||
224 | repeat | ||
225 | if _with_0 ~= nil then | ||
226 | _accum_1 = 1 | ||
227 | break | ||
228 | end | ||
229 | until true | ||
230 | _with_0 = _accum_1 | ||
231 | _accum_0 = _with_0 | ||
232 | break | ||
233 | end | ||
234 | a = _accum_0 | ||
235 | end | ||
236 | do | ||
237 | local a | ||
238 | local _accum_0 | ||
239 | for i = 1, 100 do | ||
240 | local x = tb[i] | ||
241 | if x ~= nil then | ||
242 | local _des_0 = 1 | ||
243 | if _des_0 then | ||
244 | x.id = _des_0 | ||
245 | _accum_0 = x | ||
246 | break | ||
247 | end | ||
248 | end | ||
249 | end | ||
250 | a = _accum_0 | ||
251 | end | ||
190 | return nil | 252 | return nil |
diff --git a/src/3rdParty/efsw/FileWatcherGeneric.cpp b/src/3rdParty/efsw/FileWatcherGeneric.cpp index 3f3c52e..468d27c 100644 --- a/src/3rdParty/efsw/FileWatcherGeneric.cpp +++ b/src/3rdParty/efsw/FileWatcherGeneric.cpp | |||
@@ -25,7 +25,7 @@ FileWatcherGeneric::~FileWatcherGeneric() { | |||
25 | } | 25 | } |
26 | 26 | ||
27 | WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, | 27 | WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, |
28 | bool recursive, const std::vector<WatcherOption>& options ) { | 28 | bool recursive, const std::vector<WatcherOption>& /*options*/ ) { |
29 | std::string dir( directory ); | 29 | std::string dir( directory ); |
30 | 30 | ||
31 | FileSystem::dirAddSlashAtEnd( dir ); | 31 | FileSystem::dirAddSlashAtEnd( dir ); |
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index fe6e726..945e1d7 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
@@ -167,12 +167,11 @@ std::string ExistentialOp_t::to_string(void*) const { | |||
167 | std::string TableAppendingOp_t::to_string(void*) const { | 167 | std::string TableAppendingOp_t::to_string(void*) const { |
168 | return "[]"s; | 168 | return "[]"s; |
169 | } | 169 | } |
170 | std::string PlainItem_t::to_string(void *) const { | 170 | std::string PlainItem_t::to_string(void*) const { |
171 | return {}; | 171 | return {}; |
172 | } | 172 | } |
173 | std::string GlobalOp_t::to_string(void* ud) const { | 173 | std::string GlobalOp_t::to_string(void*) const { |
174 | auto info = reinterpret_cast<YueFormat*>(ud); | 174 | return "*"s; |
175 | return info->convert(this); | ||
176 | } | 175 | } |
177 | std::string ExportDefault_t::to_string(void*) const { | 176 | std::string ExportDefault_t::to_string(void*) const { |
178 | return "default"s; | 177 | return "default"s; |
@@ -188,9 +187,17 @@ std::string ConstValue_t::to_string(void* ud) const { | |||
188 | std::string NotIn_t::to_string(void*) const { | 187 | std::string NotIn_t::to_string(void*) const { |
189 | return {}; | 188 | return {}; |
190 | } | 189 | } |
190 | std::string Break_t::to_string(void*) const { | ||
191 | return "break"s; | ||
192 | } | ||
193 | std::string Continue_t::to_string(void*) const { | ||
194 | return "continue"s; | ||
195 | } | ||
191 | std::string BreakLoop_t::to_string(void* ud) const { | 196 | std::string BreakLoop_t::to_string(void* ud) const { |
192 | auto info = reinterpret_cast<YueFormat*>(ud); | 197 | if (value) { |
193 | return info->convert(this); | 198 | return type->to_string(ud) + ' ' + value->to_string(ud); |
199 | } | ||
200 | return type->to_string(ud); | ||
194 | } | 201 | } |
195 | std::string YueLineComment_t::to_string(void* ud) const { | 202 | std::string YueLineComment_t::to_string(void* ud) const { |
196 | auto info = reinterpret_cast<YueFormat*>(ud); | 203 | auto info = reinterpret_cast<YueFormat*>(ud); |
@@ -297,6 +304,17 @@ std::string ImportAs_t::to_string(void* ud) const { | |||
297 | } | 304 | } |
298 | return join(temp, " "s); | 305 | return join(temp, " "s); |
299 | } | 306 | } |
307 | std::string ImportGlobal_t::to_string(void* ud) const { | ||
308 | str_list temp; | ||
309 | for (auto seg : segs.objects()) { | ||
310 | temp.emplace_back(seg->to_string(ud)); | ||
311 | } | ||
312 | auto item = join(temp, "."s); | ||
313 | if (target) { | ||
314 | return item + " as "s + target->to_string(ud); | ||
315 | } | ||
316 | return item; | ||
317 | } | ||
300 | std::string Import_t::to_string(void* ud) const { | 318 | std::string Import_t::to_string(void* ud) const { |
301 | if (ast_is<FromImport_t>(content)) { | 319 | if (ast_is<FromImport_t>(content)) { |
302 | return content->to_string(ud); | 320 | return content->to_string(ud); |
@@ -324,6 +342,12 @@ std::string Backcall_t::to_string(void* ud) const { | |||
324 | temp.emplace_back(value->to_string(ud)); | 342 | temp.emplace_back(value->to_string(ud)); |
325 | return join(temp, " "sv); | 343 | return join(temp, " "sv); |
326 | } | 344 | } |
345 | std::string SubBackcall_t::to_string(void* ud) const { | ||
346 | str_list temp; | ||
347 | temp.emplace_back(arrow->to_string(ud)); | ||
348 | temp.emplace_back(value->to_string(ud)); | ||
349 | return join(temp, " "sv); | ||
350 | } | ||
327 | std::string PipeBody_t::to_string(void* ud) const { | 351 | std::string PipeBody_t::to_string(void* ud) const { |
328 | auto info = reinterpret_cast<YueFormat*>(ud); | 352 | auto info = reinterpret_cast<YueFormat*>(ud); |
329 | str_list temp; | 353 | str_list temp; |
@@ -359,8 +383,8 @@ std::string With_t::to_string(void* ud) const { | |||
359 | str_list temp{ | 383 | str_list temp{ |
360 | eop ? "with?"s : "with"s, | 384 | eop ? "with?"s : "with"s, |
361 | valueList->to_string(ud)}; | 385 | valueList->to_string(ud)}; |
362 | if (assigns) { | 386 | if (assign) { |
363 | temp.push_back(assigns->to_string(ud)); | 387 | temp.push_back(':' + assign->to_string(ud)); |
364 | } | 388 | } |
365 | if (body.is<Statement_t>()) { | 389 | if (body.is<Statement_t>()) { |
366 | return join(temp, " "sv) + " do "s + body->to_string(ud); | 390 | return join(temp, " "sv) + " do "s + body->to_string(ud); |
@@ -406,6 +430,9 @@ std::string SwitchCase_t::to_string(void* ud) const { | |||
406 | std::string Switch_t::to_string(void* ud) const { | 430 | std::string Switch_t::to_string(void* ud) const { |
407 | auto info = reinterpret_cast<YueFormat*>(ud); | 431 | auto info = reinterpret_cast<YueFormat*>(ud); |
408 | str_list temp{"switch "s + target->to_string(ud)}; | 432 | str_list temp{"switch "s + target->to_string(ud)}; |
433 | if (assignment) { | ||
434 | temp.back().append(assignment->to_string(ud)); | ||
435 | } | ||
409 | info->pushScope(); | 436 | info->pushScope(); |
410 | for (auto branch : branches.objects()) { | 437 | for (auto branch : branches.objects()) { |
411 | temp.emplace_back(info->ind() + branch->to_string(ud)); | 438 | temp.emplace_back(info->ind() + branch->to_string(ud)); |
@@ -449,41 +476,75 @@ std::string If_t::to_string(void* ud) const { | |||
449 | temp.back() += " then"s; | 476 | temp.back() += " then"s; |
450 | } | 477 | } |
451 | ++it; | 478 | ++it; |
452 | bool condition = true; | 479 | enum class NType { |
480 | Cond, | ||
481 | Stat, | ||
482 | Block | ||
483 | }; | ||
484 | NType lastType = NType::Cond; | ||
453 | for (; it != nodes.objects().end(); ++it) { | 485 | for (; it != nodes.objects().end(); ++it) { |
454 | auto node = *it; | 486 | auto node = *it; |
455 | switch (node->get_id()) { | 487 | switch (node->get_id()) { |
456 | case id<IfCond_t>(): | 488 | case id<IfCond_t>(): |
457 | temp.emplace_back(info->ind() + "elseif "s + node->to_string(ud)); | 489 | temp.emplace_back(info->ind() + "elseif "s + node->to_string(ud)); |
458 | condition = true; | 490 | lastType = NType::Cond; |
459 | break; | 491 | break; |
460 | case id<Statement_t>(): { | 492 | case id<Statement_t>(): { |
461 | if (condition) { | 493 | switch (lastType) { |
462 | temp.back() += " then "s + node->to_string(ud); | 494 | case NType::Cond: |
463 | } else { | 495 | temp.back() += " then "s + node->to_string(ud); |
464 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | 496 | break; |
497 | case NType::Stat: | ||
498 | if (temp.back().back() == '\n') { | ||
499 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | ||
500 | } else { | ||
501 | temp.back() += " else "s + node->to_string(ud); | ||
502 | } | ||
503 | break; | ||
504 | case NType::Block: | ||
505 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | ||
506 | break; | ||
465 | } | 507 | } |
466 | condition = false; | 508 | lastType = NType::Stat; |
467 | break; | 509 | break; |
468 | } | 510 | } |
469 | case id<Block_t>(): { | 511 | case id<Block_t>(): { |
470 | if (condition) { | 512 | switch (lastType) { |
471 | info->pushScope(); | 513 | case NType::Cond: { |
472 | temp.emplace_back(node->to_string(ud)); | 514 | info->pushScope(); |
473 | if (temp.back().empty()) { | 515 | temp.emplace_back(node->to_string(ud)); |
474 | temp.back() = info->ind() + "--"s; | 516 | if (temp.back().empty()) { |
517 | temp.back() = info->ind() + "--"s; | ||
518 | } | ||
519 | info->popScope(); | ||
520 | break; | ||
521 | } | ||
522 | case NType::Stat: { | ||
523 | if (temp.back().back() == '\n') { | ||
524 | temp.emplace_back(info->ind() + "else"s); | ||
525 | } else { | ||
526 | temp.back() += " else"s; | ||
527 | } | ||
528 | info->pushScope(); | ||
529 | temp.emplace_back(node->to_string(ud)); | ||
530 | if (temp.back().empty()) { | ||
531 | temp.back() = info->ind() + "--"s; | ||
532 | } | ||
533 | info->popScope(); | ||
534 | break; | ||
475 | } | 535 | } |
476 | info->popScope(); | 536 | case NType::Block: { |
477 | } else { | 537 | temp.emplace_back(info->ind() + "else"s); |
478 | temp.emplace_back(info->ind() + "else"s); | 538 | info->pushScope(); |
479 | info->pushScope(); | 539 | temp.emplace_back(node->to_string(ud)); |
480 | temp.emplace_back(node->to_string(ud)); | 540 | if (temp.back().empty()) { |
481 | if (temp.back().empty()) { | 541 | temp.back() = info->ind() + "--"s; |
482 | temp.back() = info->ind() + "--"s; | 542 | } |
543 | info->popScope(); | ||
544 | break; | ||
483 | } | 545 | } |
484 | info->popScope(); | ||
485 | } | 546 | } |
486 | condition = false; | 547 | lastType = NType::Block; |
487 | break; | 548 | break; |
488 | } | 549 | } |
489 | } | 550 | } |
@@ -511,10 +572,10 @@ std::string While_t::to_string(void* ud) const { | |||
511 | } | 572 | } |
512 | std::string Repeat_t::to_string(void* ud) const { | 573 | std::string Repeat_t::to_string(void* ud) const { |
513 | auto info = reinterpret_cast<YueFormat*>(ud); | 574 | auto info = reinterpret_cast<YueFormat*>(ud); |
514 | str_list temp; | 575 | if (body.is<Statement_t>()) { |
515 | if (body->content.is<Statement_t>()) { | 576 | return "repeat "s + body->to_string(ud) + " until "s + condition->to_string(ud); |
516 | temp.emplace_back("repeat "s + body->to_string(ud)); | ||
517 | } else { | 577 | } else { |
578 | str_list temp; | ||
518 | temp.emplace_back("repeat"s); | 579 | temp.emplace_back("repeat"s); |
519 | info->pushScope(); | 580 | info->pushScope(); |
520 | temp.emplace_back(body->to_string(ud)); | 581 | temp.emplace_back(body->to_string(ud)); |
@@ -522,9 +583,9 @@ std::string Repeat_t::to_string(void* ud) const { | |||
522 | temp.back() = info->ind() + "--"s; | 583 | temp.back() = info->ind() + "--"s; |
523 | } | 584 | } |
524 | info->popScope(); | 585 | info->popScope(); |
586 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
587 | return join(temp, "\n"sv); | ||
525 | } | 588 | } |
526 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
527 | return join(temp, "\n"sv); | ||
528 | } | 589 | } |
529 | std::string ForStepValue_t::to_string(void* ud) const { | 590 | std::string ForStepValue_t::to_string(void* ud) const { |
530 | return value->to_string(ud); | 591 | return value->to_string(ud); |
@@ -596,10 +657,13 @@ std::string CatchBlock_t::to_string(void* ud) const { | |||
596 | std::string Try_t::to_string(void* ud) const { | 657 | std::string Try_t::to_string(void* ud) const { |
597 | auto info = reinterpret_cast<YueFormat*>(ud); | 658 | auto info = reinterpret_cast<YueFormat*>(ud); |
598 | str_list temp; | 659 | str_list temp; |
660 | temp.emplace_back("try"s); | ||
661 | if (eop) { | ||
662 | temp.back() += eop->to_string(ud); | ||
663 | } | ||
599 | if (func.is<Exp_t>()) { | 664 | if (func.is<Exp_t>()) { |
600 | temp.emplace_back("try "s + func->to_string(ud)); | 665 | temp.back() += (" "s + func->to_string(ud)); |
601 | } else { | 666 | } else { |
602 | temp.emplace_back("try"s); | ||
603 | info->pushScope(); | 667 | info->pushScope(); |
604 | temp.emplace_back(func->to_string(ud)); | 668 | temp.emplace_back(func->to_string(ud)); |
605 | if (temp.back().empty()) { | 669 | if (temp.back().empty()) { |
@@ -851,6 +915,12 @@ std::string Exp_t::to_string(void* ud) const { | |||
851 | } | 915 | } |
852 | return join(temp, " "sv); | 916 | return join(temp, " "sv); |
853 | } | 917 | } |
918 | std::string ReversedIndex_t::to_string(void* ud) const { | ||
919 | if (modifier) { | ||
920 | return "[# - "s + modifier->to_string(ud) + ']'; | ||
921 | } | ||
922 | return "[#]"s; | ||
923 | } | ||
854 | std::string Callable_t::to_string(void* ud) const { | 924 | std::string Callable_t::to_string(void* ud) const { |
855 | return item->to_string(ud); | 925 | return item->to_string(ud); |
856 | } | 926 | } |
@@ -937,6 +1007,51 @@ std::string DoubleString_t::to_string(void* ud) const { | |||
937 | } | 1007 | } |
938 | return '"' + join(temp) + '"'; | 1008 | return '"' + join(temp) + '"'; |
939 | } | 1009 | } |
1010 | std::string YAMLIndent_t::to_string(void* ud) const { | ||
1011 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
1012 | return info->convert(this); | ||
1013 | } | ||
1014 | std::string YAMLLineInner_t::to_string(void* ud) const { | ||
1015 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
1016 | return info->convert(this); | ||
1017 | } | ||
1018 | std::string YAMLLineContent_t::to_string(void* ud) const { | ||
1019 | if (content.is<Exp_t>()) { | ||
1020 | return "#{"s + content->to_string(ud) + '}'; | ||
1021 | } | ||
1022 | return content->to_string(ud); | ||
1023 | } | ||
1024 | std::string YAMLLine_t::to_string(void* ud) const { | ||
1025 | str_list temp; | ||
1026 | for (auto seg : segments.objects()) { | ||
1027 | temp.emplace_back(seg->to_string(ud)); | ||
1028 | } | ||
1029 | return join(temp); | ||
1030 | } | ||
1031 | std::string YAMLMultiline_t::to_string(void* ud) const { | ||
1032 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
1033 | int currentIndent = info->indent; | ||
1034 | str_list temp; | ||
1035 | int lastIndent = -1; | ||
1036 | for (auto line_ : lines.objects()) { | ||
1037 | auto line = static_cast<YAMLLine_t*>(line_); | ||
1038 | auto indent = line->indent->to_string(ud); | ||
1039 | int ind = 0; | ||
1040 | for (auto c : indent) { | ||
1041 | if (c == ' ') ind++; | ||
1042 | if (c == '\t') ind += 4; | ||
1043 | } | ||
1044 | if (lastIndent < ind) { | ||
1045 | info->pushScope(); | ||
1046 | } else if (lastIndent > ind) { | ||
1047 | info->popScope(); | ||
1048 | } | ||
1049 | lastIndent = ind; | ||
1050 | temp.emplace_back(indent + line->to_string(ud)); | ||
1051 | } | ||
1052 | info->indent = currentIndent; | ||
1053 | return "|\n" + join(temp, "\n"sv) + '\n'; | ||
1054 | } | ||
940 | std::string String_t::to_string(void* ud) const { | 1055 | std::string String_t::to_string(void* ud) const { |
941 | return str->to_string(ud); | 1056 | return str->to_string(ud); |
942 | } | 1057 | } |
@@ -1125,7 +1240,7 @@ std::string ClassDecl_t::to_string(void* ud) const { | |||
1125 | return line; | 1240 | return line; |
1126 | } | 1241 | } |
1127 | std::string GlobalValues_t::to_string(void* ud) const { | 1242 | std::string GlobalValues_t::to_string(void* ud) const { |
1128 | auto line = nameList->to_string(ud); | 1243 | std::string line = nameList->to_string(ud); |
1129 | if (valueList) { | 1244 | if (valueList) { |
1130 | if (valueList.is<TableBlock_t>()) { | 1245 | if (valueList.is<TableBlock_t>()) { |
1131 | line += " =\n"s + valueList->to_string(ud); | 1246 | line += " =\n"s + valueList->to_string(ud); |
@@ -1136,7 +1251,7 @@ std::string GlobalValues_t::to_string(void* ud) const { | |||
1136 | return line; | 1251 | return line; |
1137 | } | 1252 | } |
1138 | std::string Global_t::to_string(void* ud) const { | 1253 | std::string Global_t::to_string(void* ud) const { |
1139 | return "global "s + item->to_string(ud); | 1254 | return "global "s + (constAttrib ? "const "s : ""s) + item->to_string(ud); |
1140 | } | 1255 | } |
1141 | std::string Export_t::to_string(void* ud) const { | 1256 | std::string Export_t::to_string(void* ud) const { |
1142 | auto line = "export"s; | 1257 | auto line = "export"s; |
@@ -1235,6 +1350,9 @@ std::string FnArgDef_t::to_string(void* ud) const { | |||
1235 | if (op) { | 1350 | if (op) { |
1236 | line += op->to_string(ud); | 1351 | line += op->to_string(ud); |
1237 | } | 1352 | } |
1353 | if (label) { | ||
1354 | line += '`' + label->to_string(ud); | ||
1355 | } | ||
1238 | if (defaultValue) { | 1356 | if (defaultValue) { |
1239 | line += " = "s + defaultValue->to_string(ud); | 1357 | line += " = "s + defaultValue->to_string(ud); |
1240 | } | 1358 | } |
@@ -1257,6 +1375,9 @@ std::string FnArgDefList_t::to_string(void* ud) const { | |||
1257 | } | 1375 | } |
1258 | if (varArg) { | 1376 | if (varArg) { |
1259 | temp.emplace_back(info->ind() + varArg->to_string(ud)); | 1377 | temp.emplace_back(info->ind() + varArg->to_string(ud)); |
1378 | if (label) { | ||
1379 | temp.back().append('`' + label->to_string(ud)); | ||
1380 | } | ||
1260 | } | 1381 | } |
1261 | return join(temp, "\n"sv); | 1382 | return join(temp, "\n"sv); |
1262 | } else { | 1383 | } else { |
@@ -1265,6 +1386,9 @@ std::string FnArgDefList_t::to_string(void* ud) const { | |||
1265 | } | 1386 | } |
1266 | if (varArg) { | 1387 | if (varArg) { |
1267 | temp.emplace_back(varArg->to_string(ud)); | 1388 | temp.emplace_back(varArg->to_string(ud)); |
1389 | if (label) { | ||
1390 | temp.back().append('`' + label->to_string(ud)); | ||
1391 | } | ||
1268 | } | 1392 | } |
1269 | return join(temp, ", "sv); | 1393 | return join(temp, ", "sv); |
1270 | } | 1394 | } |
@@ -1546,3 +1670,4 @@ std::string File_t::to_string(void* ud) const { | |||
1546 | } // namespace yue | 1670 | } // namespace yue |
1547 | 1671 | ||
1548 | } // namespace parserlib | 1672 | } // namespace parserlib |
1673 | |||
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 5e70645..6e1bb88 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -233,8 +233,15 @@ AST_NODE(ImportAs) | |||
233 | AST_MEMBER(ImportAs, &literal, &target) | 233 | AST_MEMBER(ImportAs, &literal, &target) |
234 | AST_END(ImportAs) | 234 | AST_END(ImportAs) |
235 | 235 | ||
236 | AST_NODE(ImportGlobal) | ||
237 | ast_ptr<true, Seperator_t> sep; | ||
238 | ast_list<true, UnicodeName_t> segs; | ||
239 | ast_ptr<false, Variable_t> target; | ||
240 | AST_MEMBER(ImportGlobal, &sep, &segs, &target) | ||
241 | AST_END(ImportGlobal) | ||
242 | |||
236 | AST_NODE(Import) | 243 | AST_NODE(Import) |
237 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t> content; | 244 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t, ImportGlobal_t> content; |
238 | AST_MEMBER(Import, &content) | 245 | AST_MEMBER(Import, &content) |
239 | AST_END(Import) | 246 | AST_END(Import) |
240 | 247 | ||
@@ -273,6 +280,8 @@ AST_NODE(ExpList) | |||
273 | ast_ptr<true, Seperator_t> sep; | 280 | ast_ptr<true, Seperator_t> sep; |
274 | ast_list<true, Exp_t> exprs; | 281 | ast_list<true, Exp_t> exprs; |
275 | AST_MEMBER(ExpList, &sep, &exprs) | 282 | AST_MEMBER(ExpList, &sep, &exprs) |
283 | bool followStmtProcessed = false; | ||
284 | Statement_t* followStmt = nullptr; | ||
276 | AST_END(ExpList) | 285 | AST_END(ExpList) |
277 | 286 | ||
278 | AST_NODE(Return) | 287 | AST_NODE(Return) |
@@ -285,9 +294,9 @@ AST_END(Return) | |||
285 | AST_NODE(With) | 294 | AST_NODE(With) |
286 | ast_ptr<false, ExistentialOp_t> eop; | 295 | ast_ptr<false, ExistentialOp_t> eop; |
287 | ast_ptr<true, ExpList_t> valueList; | 296 | ast_ptr<true, ExpList_t> valueList; |
288 | ast_ptr<false, Assign_t> assigns; | 297 | ast_ptr<false, Assign_t> assign; |
289 | ast_sel<true, Block_t, Statement_t> body; | 298 | ast_sel<true, Block_t, Statement_t> body; |
290 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) | 299 | AST_MEMBER(With, &eop, &valueList, &assign, &body) |
291 | AST_END(With) | 300 | AST_END(With) |
292 | 301 | ||
293 | AST_NODE(SwitchList) | 302 | AST_NODE(SwitchList) |
@@ -302,20 +311,21 @@ AST_NODE(SwitchCase) | |||
302 | AST_MEMBER(SwitchCase, &condition, &body) | 311 | AST_MEMBER(SwitchCase, &condition, &body) |
303 | AST_END(SwitchCase) | 312 | AST_END(SwitchCase) |
304 | 313 | ||
314 | AST_NODE(Assignment) | ||
315 | ast_ptr<false, ExpList_t> expList; | ||
316 | ast_ptr<true, Assign_t> assign; | ||
317 | AST_MEMBER(Assignment, &expList, &assign) | ||
318 | AST_END(Assignment) | ||
319 | |||
305 | AST_NODE(Switch) | 320 | AST_NODE(Switch) |
306 | ast_ptr<true, Exp_t> target; | 321 | ast_ptr<true, Exp_t> target; |
322 | ast_ptr<false, Assignment_t> assignment; | ||
307 | ast_ptr<true, Seperator_t> sep; | 323 | ast_ptr<true, Seperator_t> sep; |
308 | ast_list<true, SwitchCase_t> branches; | 324 | ast_list<true, SwitchCase_t> branches; |
309 | ast_sel<false, Block_t, Statement_t> lastBranch; | 325 | ast_sel<false, Block_t, Statement_t> lastBranch; |
310 | AST_MEMBER(Switch, &target, &sep, &branches, &lastBranch) | 326 | AST_MEMBER(Switch, &target, &assignment, &sep, &branches, &lastBranch) |
311 | AST_END(Switch) | 327 | AST_END(Switch) |
312 | 328 | ||
313 | AST_NODE(Assignment) | ||
314 | ast_ptr<false, ExpList_t> expList; | ||
315 | ast_ptr<true, Assign_t> assign; | ||
316 | AST_MEMBER(Assignment, &expList, &assign) | ||
317 | AST_END(Assignment) | ||
318 | |||
319 | AST_NODE(IfCond) | 329 | AST_NODE(IfCond) |
320 | ast_ptr<true, Exp_t> condition; | 330 | ast_ptr<true, Exp_t> condition; |
321 | ast_ptr<false, Assignment_t> assignment; | 331 | ast_ptr<false, Assignment_t> assignment; |
@@ -343,7 +353,7 @@ AST_NODE(While) | |||
343 | AST_END(While) | 353 | AST_END(While) |
344 | 354 | ||
345 | AST_NODE(Repeat) | 355 | AST_NODE(Repeat) |
346 | ast_ptr<true, Body_t> body; | 356 | ast_sel<true, Block_t, Statement_t> body; |
347 | ast_ptr<true, Exp_t> condition; | 357 | ast_ptr<true, Exp_t> condition; |
348 | AST_MEMBER(Repeat, &body, &condition) | 358 | AST_MEMBER(Repeat, &body, &condition) |
349 | AST_END(Repeat) | 359 | AST_END(Repeat) |
@@ -381,9 +391,10 @@ AST_NODE(CatchBlock) | |||
381 | AST_END(CatchBlock) | 391 | AST_END(CatchBlock) |
382 | 392 | ||
383 | AST_NODE(Try) | 393 | AST_NODE(Try) |
394 | ast_ptr<false, ExistentialOp_t> eop; | ||
384 | ast_sel<true, Block_t, Exp_t> func; | 395 | ast_sel<true, Block_t, Exp_t> func; |
385 | ast_ptr<false, CatchBlock_t> catchBlock; | 396 | ast_ptr<false, CatchBlock_t> catchBlock; |
386 | AST_MEMBER(Try, &func, &catchBlock) | 397 | AST_MEMBER(Try, &eop, &func, &catchBlock) |
387 | AST_END(Try) | 398 | AST_END(Try) |
388 | 399 | ||
389 | AST_NODE(Comprehension) | 400 | AST_NODE(Comprehension) |
@@ -547,8 +558,8 @@ AST_NODE(SimpleValue) | |||
547 | ast_sel<true, | 558 | ast_sel<true, |
548 | TableLit_t, ConstValue_t, | 559 | TableLit_t, ConstValue_t, |
549 | If_t, Switch_t, With_t, ClassDecl_t, | 560 | If_t, Switch_t, With_t, ClassDecl_t, |
550 | ForEach_t, For_t, While_t, Do_t, Try_t, | 561 | ForEach_t, For_t, While_t, Repeat_t, |
551 | UnaryValue_t, | 562 | Do_t, Try_t, UnaryValue_t, |
552 | TblComprehension_t, Comprehension_t, | 563 | TblComprehension_t, Comprehension_t, |
553 | FunLit_t, Num_t, VarArg_t> value; | 564 | FunLit_t, Num_t, VarArg_t> value; |
554 | AST_MEMBER(SimpleValue, &value) | 565 | AST_MEMBER(SimpleValue, &value) |
@@ -587,8 +598,31 @@ AST_NODE(DoubleString) | |||
587 | AST_MEMBER(DoubleString, &sep, &segments) | 598 | AST_MEMBER(DoubleString, &sep, &segments) |
588 | AST_END(DoubleString) | 599 | AST_END(DoubleString) |
589 | 600 | ||
601 | AST_LEAF(YAMLIndent) | ||
602 | AST_END(YAMLIndent) | ||
603 | |||
604 | AST_LEAF(YAMLLineInner) | ||
605 | AST_END(YAMLLineInner) | ||
606 | |||
607 | AST_NODE(YAMLLineContent) | ||
608 | ast_sel<true, YAMLLineInner_t, Exp_t> content; | ||
609 | AST_MEMBER(YAMLLineContent, &content) | ||
610 | AST_END(YAMLLineContent) | ||
611 | |||
612 | AST_NODE(YAMLLine) | ||
613 | ast_ptr<true, YAMLIndent_t> indent; | ||
614 | ast_list<true, YAMLLineContent_t> segments; | ||
615 | AST_MEMBER(YAMLLine, &indent, &segments) | ||
616 | AST_END(YAMLLine) | ||
617 | |||
618 | AST_NODE(YAMLMultiline) | ||
619 | ast_ptr<true, Seperator_t> sep; | ||
620 | ast_list<true, YAMLLine_t> lines; | ||
621 | AST_MEMBER(YAMLMultiline, &sep, &lines) | ||
622 | AST_END(YAMLMultiline) | ||
623 | |||
590 | AST_NODE(String) | 624 | AST_NODE(String) |
591 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t> str; | 625 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t, YAMLMultiline_t> str; |
592 | AST_MEMBER(String, &str) | 626 | AST_MEMBER(String, &str) |
593 | AST_END(String) | 627 | AST_END(String) |
594 | 628 | ||
@@ -639,9 +673,14 @@ AST_END(TableAppendingOp) | |||
639 | AST_LEAF(PlainItem) | 673 | AST_LEAF(PlainItem) |
640 | AST_END(PlainItem) | 674 | AST_END(PlainItem) |
641 | 675 | ||
676 | AST_NODE(ReversedIndex) | ||
677 | ast_ptr<false, Exp_t> modifier; | ||
678 | AST_MEMBER(ReversedIndex, &modifier) | ||
679 | AST_END(ReversedIndex) | ||
680 | |||
642 | AST_NODE(ChainValue) | 681 | AST_NODE(ChainValue) |
643 | ast_ptr<true, Seperator_t> sep; | 682 | ast_ptr<true, Seperator_t> sep; |
644 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, | 683 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, ReversedIndex_t, |
645 | /*non-syntax-rule*/ PlainItem_t> items; | 684 | /*non-syntax-rule*/ PlainItem_t> items; |
646 | AST_MEMBER(ChainValue, &sep, &items) | 685 | AST_MEMBER(ChainValue, &sep, &items) |
647 | AST_END(ChainValue) | 686 | AST_END(ChainValue) |
@@ -725,8 +764,9 @@ AST_LEAF(GlobalOp) | |||
725 | AST_END(GlobalOp) | 764 | AST_END(GlobalOp) |
726 | 765 | ||
727 | AST_NODE(Global) | 766 | AST_NODE(Global) |
767 | ast_ptr<false, ConstAttrib_t> constAttrib; | ||
728 | ast_sel<true, ClassDecl_t, GlobalOp_t, GlobalValues_t> item; | 768 | ast_sel<true, ClassDecl_t, GlobalOp_t, GlobalValues_t> item; |
729 | AST_MEMBER(Global, &item) | 769 | AST_MEMBER(Global, &constAttrib, &item) |
730 | AST_END(Global) | 770 | AST_END(Global) |
731 | 771 | ||
732 | AST_LEAF(ExportDefault) | 772 | AST_LEAF(ExportDefault) |
@@ -740,17 +780,19 @@ AST_NODE(Export) | |||
740 | AST_END(Export) | 780 | AST_END(Export) |
741 | 781 | ||
742 | AST_NODE(FnArgDef) | 782 | AST_NODE(FnArgDef) |
743 | ast_sel<true, Variable_t, SelfItem_t> name; | 783 | ast_sel<true, Variable_t, SelfItem_t, SimpleTable_t, TableLit_t> name; |
744 | ast_ptr<false, ExistentialOp_t> op; | 784 | ast_ptr<false, ExistentialOp_t> op; |
785 | ast_ptr<false, Name_t> label; | ||
745 | ast_ptr<false, Exp_t> defaultValue; | 786 | ast_ptr<false, Exp_t> defaultValue; |
746 | AST_MEMBER(FnArgDef, &name, &op, &defaultValue) | 787 | AST_MEMBER(FnArgDef, &name, &op, &label, &defaultValue) |
747 | AST_END(FnArgDef) | 788 | AST_END(FnArgDef) |
748 | 789 | ||
749 | AST_NODE(FnArgDefList) | 790 | AST_NODE(FnArgDefList) |
750 | ast_ptr<true, Seperator_t> sep; | 791 | ast_ptr<true, Seperator_t> sep; |
751 | ast_list<false, FnArgDef_t> definitions; | 792 | ast_list<false, FnArgDef_t> definitions; |
752 | ast_ptr<false, VarArg_t> varArg; | 793 | ast_ptr<false, VarArg_t> varArg; |
753 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg) | 794 | ast_ptr<false, Name_t> label; |
795 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg, &label) | ||
754 | AST_END(FnArgDefList) | 796 | AST_END(FnArgDefList) |
755 | 797 | ||
756 | AST_NODE(OuterVarShadow) | 798 | AST_NODE(OuterVarShadow) |
@@ -838,9 +880,15 @@ AST_NODE(UnaryExp) | |||
838 | AST_MEMBER(UnaryExp, &ops, &expos, &inExp) | 880 | AST_MEMBER(UnaryExp, &ops, &expos, &inExp) |
839 | AST_END(UnaryExp) | 881 | AST_END(UnaryExp) |
840 | 882 | ||
883 | AST_NODE(SubBackcall) | ||
884 | ast_ptr<true, FnArrowBack_t> arrow; | ||
885 | ast_ptr<true, ChainValue_t> value; | ||
886 | AST_MEMBER(SubBackcall, &arrow, &value) | ||
887 | AST_END(SubBackcall) | ||
888 | |||
841 | AST_NODE(ExpListAssign) | 889 | AST_NODE(ExpListAssign) |
842 | ast_ptr<true, ExpList_t> expList; | 890 | ast_ptr<true, ExpList_t> expList; |
843 | ast_sel<false, Update_t, Assign_t> action; | 891 | ast_sel<false, Update_t, Assign_t, SubBackcall_t> action; |
844 | AST_MEMBER(ExpListAssign, &expList, &action) | 892 | AST_MEMBER(ExpListAssign, &expList, &action) |
845 | AST_END(ExpListAssign) | 893 | AST_END(ExpListAssign) |
846 | 894 | ||
@@ -856,7 +904,17 @@ AST_NODE(WhileLine) | |||
856 | AST_MEMBER(WhileLine, &type, &condition) | 904 | AST_MEMBER(WhileLine, &type, &condition) |
857 | AST_END(WhileLine) | 905 | AST_END(WhileLine) |
858 | 906 | ||
859 | AST_LEAF(BreakLoop) | 907 | AST_LEAF(Break) |
908 | AST_END(Break) | ||
909 | |||
910 | AST_LEAF(Continue) | ||
911 | AST_END(Continue) | ||
912 | |||
913 | AST_NODE(BreakLoop) | ||
914 | ast_sel<true, Break_t, Continue_t> type; | ||
915 | ast_ptr<false, Exp_t> value; | ||
916 | AST_MEMBER(BreakLoop, &type, &value) | ||
917 | std::string varBWV; | ||
860 | AST_END(BreakLoop) | 918 | AST_END(BreakLoop) |
861 | 919 | ||
862 | AST_NODE(PipeBody) | 920 | AST_NODE(PipeBody) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 590c502..33161a7 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
78 | "close"s // Lua 5.4 | 78 | "close"s // Lua 5.4 |
79 | }; | 79 | }; |
80 | 80 | ||
81 | const std::string_view version = "0.27.5"sv; | 81 | const std::string_view version = "0.29.4"sv; |
82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
83 | 83 | ||
84 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
@@ -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>(): { |
@@ -1968,7 +1982,7 @@ private: | |||
1968 | return indent() + "local "s + join(defs, ", "sv); | 1982 | return indent() + "local "s + join(defs, ", "sv); |
1969 | } | 1983 | } |
1970 | 1984 | ||
1971 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 1985 | std::string getDestructureDefine(ExpListAssign_t* assignment) { |
1972 | auto info = extractDestructureInfo(assignment, true, false); | 1986 | auto info = extractDestructureInfo(assignment, true, false); |
1973 | if (!info.destructures.empty()) { | 1987 | if (!info.destructures.empty()) { |
1974 | str_list defs; | 1988 | str_list defs; |
@@ -1999,8 +2013,31 @@ private: | |||
1999 | return clearBuf(); | 2013 | return clearBuf(); |
2000 | } | 2014 | } |
2001 | 2015 | ||
2016 | str_list getArgDestructureList(ExpListAssign_t* assignment) { | ||
2017 | str_list defs; | ||
2018 | auto info = extractDestructureInfo(assignment, true, false); | ||
2019 | if (!info.destructures.empty()) { | ||
2020 | for (const auto& des : info.destructures) { | ||
2021 | if (std::holds_alternative<Destructure>(des)) { | ||
2022 | const auto& destruct = std::get<Destructure>(des); | ||
2023 | for (const auto& item : destruct.items) { | ||
2024 | if (item.targetVar.empty()) { | ||
2025 | throw CompileError("can only destruct argument to variable"sv, item.target); | ||
2026 | } else { | ||
2027 | defs.push_back(item.targetVar); | ||
2028 | } | ||
2029 | } | ||
2030 | } else { | ||
2031 | const auto& assignment = std::get<AssignmentPtr>(des); | ||
2032 | YUEE("AST node mismatch", assignment.ptr); | ||
2033 | } | ||
2034 | } | ||
2035 | } | ||
2036 | return defs; | ||
2037 | } | ||
2038 | |||
2002 | std::string getPreDefine(ExpListAssign_t* assignment) { | 2039 | std::string getPreDefine(ExpListAssign_t* assignment) { |
2003 | auto preDefine = getDestrucureDefine(assignment); | 2040 | auto preDefine = getDestructureDefine(assignment); |
2004 | if (preDefine.empty()) { | 2041 | if (preDefine.empty()) { |
2005 | preDefine = toLocalDecl(transformAssignDefs(assignment->expList, DefOp::Mark)); | 2042 | preDefine = toLocalDecl(transformAssignDefs(assignment->expList, DefOp::Mark)); |
2006 | } | 2043 | } |
@@ -2051,13 +2088,16 @@ private: | |||
2051 | if (item.targetVar.empty()) { | 2088 | if (item.targetVar.empty()) { |
2052 | throw CompileError("can only declare variable as const"sv, item.target); | 2089 | throw CompileError("can only declare variable as const"sv, item.target); |
2053 | } | 2090 | } |
2054 | markVarConst(item.targetVar); | 2091 | markVarLocalConst(item.targetVar); |
2055 | } | 2092 | } |
2056 | } | 2093 | } |
2057 | } | 2094 | } |
2058 | } | 2095 | } |
2059 | 2096 | ||
2060 | bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | 2097 | bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { |
2098 | if (assignment->action.is<SubBackcall_t>()) { | ||
2099 | YUEE("AST node mismatch", assignment->action); | ||
2100 | } | ||
2061 | checkAssignable(assignment->expList); | 2101 | checkAssignable(assignment->expList); |
2062 | BLOCK_START | 2102 | BLOCK_START |
2063 | auto assign = ast_cast<Assign_t>(assignment->action); | 2103 | auto assign = ast_cast<Assign_t>(assignment->action); |
@@ -2320,6 +2360,17 @@ private: | |||
2320 | out.back().insert(0, preDefine); | 2360 | out.back().insert(0, preDefine); |
2321 | return false; | 2361 | return false; |
2322 | } | 2362 | } |
2363 | case id<Try_t>(): { | ||
2364 | auto tryNode = static_cast<Try_t*>(value); | ||
2365 | if (tryNode->eop) { | ||
2366 | auto assignList = assignment->expList.get(); | ||
2367 | std::string preDefine = getPreDefineLine(assignment); | ||
2368 | transformTry(tryNode, out, ExpUsage::Assignment, assignList); | ||
2369 | out.back().insert(0, preDefine); | ||
2370 | return false; | ||
2371 | } | ||
2372 | break; | ||
2373 | } | ||
2323 | case id<Switch_t>(): { | 2374 | case id<Switch_t>(): { |
2324 | auto switchNode = static_cast<Switch_t*>(value); | 2375 | auto switchNode = static_cast<Switch_t*>(value); |
2325 | auto assignList = assignment->expList.get(); | 2376 | auto assignList = assignment->expList.get(); |
@@ -2391,6 +2442,13 @@ private: | |||
2391 | out.back().insert(0, preDefine); | 2442 | out.back().insert(0, preDefine); |
2392 | return false; | 2443 | return false; |
2393 | } | 2444 | } |
2445 | case id<Repeat_t>(): { | ||
2446 | auto expList = assignment->expList.get(); | ||
2447 | std::string preDefine = getPreDefineLine(assignment); | ||
2448 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out, expList); | ||
2449 | out.back().insert(0, preDefine); | ||
2450 | return false; | ||
2451 | } | ||
2394 | case id<TableLit_t>(): { | 2452 | case id<TableLit_t>(): { |
2395 | auto tableLit = static_cast<TableLit_t*>(value); | 2453 | auto tableLit = static_cast<TableLit_t*>(value); |
2396 | if (hasSpreadExp(tableLit->values.objects())) { | 2454 | if (hasSpreadExp(tableLit->values.objects())) { |
@@ -2443,12 +2501,14 @@ private: | |||
2443 | switch (type) { | 2501 | switch (type) { |
2444 | case ChainType::HasEOP: | 2502 | case ChainType::HasEOP: |
2445 | case ChainType::EndWithColon: | 2503 | case ChainType::EndWithColon: |
2504 | case ChainType::EndWithSlice: | ||
2446 | case ChainType::MetaFieldInvocation: { | 2505 | case ChainType::MetaFieldInvocation: { |
2447 | std::string preDefine = getPreDefineLine(assignment); | 2506 | std::string preDefine = getPreDefineLine(assignment); |
2448 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); | 2507 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); |
2449 | out.back().insert(0, preDefine); | 2508 | out.back().insert(0, preDefine); |
2450 | return false; | 2509 | return false; |
2451 | } | 2510 | } |
2511 | case ChainType::HasRIndex: | ||
2452 | case ChainType::HasKeyword: | 2512 | case ChainType::HasKeyword: |
2453 | case ChainType::HasUnicode: | 2513 | case ChainType::HasUnicode: |
2454 | case ChainType::Macro: | 2514 | case ChainType::Macro: |
@@ -2464,6 +2524,10 @@ private: | |||
2464 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); | 2524 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); |
2465 | if (info.destructures.empty()) { | 2525 | if (info.destructures.empty()) { |
2466 | transformAssignmentCommon(assignment, out); | 2526 | transformAssignmentCommon(assignment, out); |
2527 | if (assignment->expList->followStmt) { | ||
2528 | transformStatement(assignment->expList->followStmt, out); | ||
2529 | assignment->expList->followStmtProcessed = true; | ||
2530 | } | ||
2467 | return true; | 2531 | return true; |
2468 | } else { | 2532 | } else { |
2469 | auto x = assignment; | 2533 | auto x = assignment; |
@@ -2729,8 +2793,12 @@ private: | |||
2729 | temp.push_back(indent() + "end"s + nlr(x)); | 2793 | temp.push_back(indent() + "end"s + nlr(x)); |
2730 | } | 2794 | } |
2731 | out.push_back(join(temp)); | 2795 | out.push_back(join(temp)); |
2796 | if (assignment->expList->followStmt) { | ||
2797 | transformStatement(assignment->expList->followStmt, out); | ||
2798 | assignment->expList->followStmtProcessed = true; | ||
2799 | } | ||
2800 | return false; | ||
2732 | } | 2801 | } |
2733 | return false; | ||
2734 | } | 2802 | } |
2735 | 2803 | ||
2736 | void transformAssignItem(ast_node* value, str_list& out) { | 2804 | void transformAssignItem(ast_node* value, str_list& out) { |
@@ -2796,20 +2864,46 @@ private: | |||
2796 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); | 2864 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); |
2797 | std::list<DestructItem> pairs; | 2865 | std::list<DestructItem> pairs; |
2798 | int index = 0; | 2866 | int index = 0; |
2867 | int count = 0; | ||
2868 | bool hasSpread = false; | ||
2799 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); | 2869 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); |
2800 | for (auto pair : *tableItems) { | 2870 | for (auto pair : *tableItems) { |
2801 | switch (pair->get_id()) { | 2871 | switch (pair->get_id()) { |
2802 | case id<Exp_t>(): | 2872 | case id<Exp_t>(): |
2803 | case id<NormalDef_t>(): { | 2873 | case id<NormalDef_t>(): { |
2874 | ++index; | ||
2804 | Exp_t* defVal = nullptr; | 2875 | Exp_t* defVal = nullptr; |
2805 | if (auto nd = ast_cast<NormalDef_t>(pair)) { | 2876 | if (auto nd = ast_cast<NormalDef_t>(pair)) { |
2806 | pair = nd->item.get(); | 2877 | pair = nd->item.get(); |
2807 | defVal = nd->defVal.get(); | 2878 | defVal = nd->defVal.get(); |
2808 | } | 2879 | } |
2809 | ++index; | 2880 | bool assignable = false; |
2810 | if (!varDefOnly && !isAssignable(static_cast<Exp_t*>(pair))) { | 2881 | try { |
2882 | assignable = isAssignable(static_cast<Exp_t*>(pair)); | ||
2883 | } catch (const CompileError& e) { | ||
2884 | if (!varDefOnly) throw e; | ||
2885 | } | ||
2886 | if (!assignable && !varDefOnly) { | ||
2887 | if (optional) break; | ||
2811 | throw CompileError("can't destructure value"sv, pair); | 2888 | throw CompileError("can't destructure value"sv, pair); |
2812 | } | 2889 | } |
2890 | ast_ptr<true, ast_node> indexItem; | ||
2891 | if (hasSpread) { | ||
2892 | int rIndex = count - index; | ||
2893 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), pair)); | ||
2894 | } else { | ||
2895 | indexItem.set(toAst<Exp_t>(std::to_string(index), pair)); | ||
2896 | } | ||
2897 | if (optional && varDefOnly && !assignable) { | ||
2898 | if (defVal) { | ||
2899 | throw CompileError("default value is not supported here"sv, defVal); | ||
2900 | } | ||
2901 | auto exp = static_cast<Exp_t*>(pair); | ||
2902 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
2903 | chain->items.push_back(indexItem); | ||
2904 | pairs.push_back({exp, Empty, chain, nullptr}); | ||
2905 | break; | ||
2906 | } | ||
2813 | auto value = singleValueFrom(pair); | 2907 | auto value = singleValueFrom(pair); |
2814 | auto item = value->item.get(); | 2908 | auto item = value->item.get(); |
2815 | ast_node* subExp = ast_cast<SimpleTable_t>(item); | 2909 | ast_node* subExp = ast_cast<SimpleTable_t>(item); |
@@ -2820,7 +2914,6 @@ private: | |||
2820 | throw CompileError("default value is not supported here"sv, defVal); | 2914 | throw CompileError("default value is not supported here"sv, defVal); |
2821 | } | 2915 | } |
2822 | } | 2916 | } |
2823 | auto indexItem = toAst<Exp_t>(std::to_string(index), value); | ||
2824 | for (auto& p : subPairs) { | 2917 | for (auto& p : subPairs) { |
2825 | if (sep) p.structure->items.push_front(sep); | 2918 | if (sep) p.structure->items.push_front(sep); |
2826 | p.structure->items.push_front(indexItem); | 2919 | p.structure->items.push_front(indexItem); |
@@ -2831,7 +2924,6 @@ private: | |||
2831 | auto varName = singleVariableFrom(exp, AccessType::None); | 2924 | auto varName = singleVariableFrom(exp, AccessType::None); |
2832 | if (varName == "_"sv) break; | 2925 | if (varName == "_"sv) break; |
2833 | auto chain = exp->new_ptr<ChainValue_t>(); | 2926 | auto chain = exp->new_ptr<ChainValue_t>(); |
2834 | auto indexItem = toAst<Exp_t>(std::to_string(index), exp); | ||
2835 | chain->items.push_back(indexItem); | 2927 | chain->items.push_back(indexItem); |
2836 | pairs.push_back({exp, | 2928 | pairs.push_back({exp, |
2837 | varName, | 2929 | varName, |
@@ -2889,7 +2981,25 @@ private: | |||
2889 | } | 2981 | } |
2890 | } | 2982 | } |
2891 | if (auto exp = np->value.as<Exp_t>()) { | 2983 | if (auto exp = np->value.as<Exp_t>()) { |
2892 | if (!varDefOnly && !isAssignable(exp)) throw CompileError("can't do destructure value"sv, exp); | 2984 | bool assignable = false; |
2985 | try { | ||
2986 | assignable = isAssignable(exp); | ||
2987 | } catch (const CompileError& e) { | ||
2988 | if (!varDefOnly) throw e; | ||
2989 | } | ||
2990 | if (!assignable && !varDefOnly) { | ||
2991 | if (optional) break; | ||
2992 | throw CompileError("can't destructure value"sv, pair); | ||
2993 | } | ||
2994 | if (optional && varDefOnly && !assignable) { | ||
2995 | if (defVal) { | ||
2996 | throw CompileError("default value is not supported here"sv, defVal); | ||
2997 | } | ||
2998 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
2999 | if (keyIndex) chain->items.push_back(keyIndex); | ||
3000 | pairs.push_back({exp, Empty, chain, nullptr}); | ||
3001 | break; | ||
3002 | } | ||
2893 | auto item = singleValueFrom(exp)->item.get(); | 3003 | auto item = singleValueFrom(exp)->item.get(); |
2894 | ast_node* subExp = ast_cast<SimpleTable_t>(item); | 3004 | 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>())) { | 3005 | if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) { |
@@ -2938,7 +3048,13 @@ private: | |||
2938 | auto tb = static_cast<TableBlockIndent_t*>(pair); | 3048 | auto tb = static_cast<TableBlockIndent_t*>(pair); |
2939 | ++index; | 3049 | ++index; |
2940 | auto subPairs = destructFromExp(tb, varDefOnly, optional); | 3050 | auto subPairs = destructFromExp(tb, varDefOnly, optional); |
2941 | auto indexItem = toAst<Exp_t>(std::to_string(index), tb); | 3051 | ast_ptr<true, ast_node> indexItem; |
3052 | if (hasSpread) { | ||
3053 | int rIndex = count - index; | ||
3054 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), tb)); | ||
3055 | } else { | ||
3056 | indexItem.set(toAst<Exp_t>(std::to_string(index), tb)); | ||
3057 | } | ||
2942 | for (auto& p : subPairs) { | 3058 | for (auto& p : subPairs) { |
2943 | if (sep) p.structure->items.push_front(sep); | 3059 | if (sep) p.structure->items.push_front(sep); |
2944 | p.structure->items.push_front(indexItem); | 3060 | p.structure->items.push_front(indexItem); |
@@ -2995,6 +3111,42 @@ private: | |||
2995 | subMetaDestruct->values.push_back(newPairDef); | 3111 | subMetaDestruct->values.push_back(newPairDef); |
2996 | break; | 3112 | break; |
2997 | } | 3113 | } |
3114 | case id<SpreadListExp_t>(): | ||
3115 | case id<SpreadExp_t>(): { | ||
3116 | ++index; | ||
3117 | if (hasSpread) { | ||
3118 | throw CompileError("duplicated spread expression"sv, pair); | ||
3119 | } | ||
3120 | hasSpread = true; | ||
3121 | for (auto item : *tableItems) { | ||
3122 | if (ast_is< | ||
3123 | SpreadListExp_t, SpreadExp_t, | ||
3124 | TableBlockIndent_t, | ||
3125 | Exp_t, NormalDef_t>(item)) { | ||
3126 | count++; | ||
3127 | } | ||
3128 | } | ||
3129 | Exp_t* exp = nullptr; | ||
3130 | if (auto se = ast_cast<SpreadExp_t>(pair)) { | ||
3131 | exp = se->exp.get(); | ||
3132 | } else { | ||
3133 | exp = ast_to<SpreadListExp_t>(pair)->exp.get(); | ||
3134 | } | ||
3135 | auto varName = singleVariableFrom(exp, AccessType::None); | ||
3136 | if (varName == "_"sv) break; | ||
3137 | int start = index; | ||
3138 | int stop = index - count - 1; | ||
3139 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
3140 | auto slice = toAst<Slice_t>( | ||
3141 | '[' + (start == 1 ? Empty : std::to_string(start)) + ',' + (stop == -1 ? Empty : std::to_string(stop)) + ']', exp); | ||
3142 | chain->items.push_back(slice); | ||
3143 | auto nil = toAst<Exp_t>("nil"sv, slice); | ||
3144 | pairs.push_back({exp, | ||
3145 | varName, | ||
3146 | chain, | ||
3147 | nil.get()}); | ||
3148 | break; | ||
3149 | } | ||
2998 | default: YUEE("AST node mismatch", pair); break; | 3150 | default: YUEE("AST node mismatch", pair); break; |
2999 | } | 3151 | } |
3000 | } | 3152 | } |
@@ -3111,7 +3263,11 @@ private: | |||
3111 | break; | 3263 | break; |
3112 | default: YUEE("AST node mismatch", destructNode); break; | 3264 | default: YUEE("AST node mismatch", destructNode); break; |
3113 | } | 3265 | } |
3114 | if (dlist->empty()) throw CompileError("expect items to be destructured"sv, destructNode); | 3266 | if (dlist->empty()) { |
3267 | if (!optional) { | ||
3268 | throw CompileError("expect items to be destructured"sv, destructNode); | ||
3269 | } | ||
3270 | } | ||
3115 | for (auto item : *dlist) { | 3271 | for (auto item : *dlist) { |
3116 | switch (item->get_id()) { | 3272 | switch (item->get_id()) { |
3117 | case id<MetaVariablePairDef_t>(): { | 3273 | case id<MetaVariablePairDef_t>(): { |
@@ -3247,7 +3403,9 @@ private: | |||
3247 | simpleValue->value.set(tab); | 3403 | simpleValue->value.set(tab); |
3248 | auto pairs = destructFromExp(newExp(simpleValue, expr), varDefOnly, optional); | 3404 | auto pairs = destructFromExp(newExp(simpleValue, expr), varDefOnly, optional); |
3249 | if (pairs.empty()) { | 3405 | if (pairs.empty()) { |
3250 | throw CompileError("expect items to be destructured"sv, tab); | 3406 | if (!optional) { |
3407 | throw CompileError("expect items to be destructured"sv, tab); | ||
3408 | } | ||
3251 | } | 3409 | } |
3252 | destruct.items = std::move(pairs); | 3410 | destruct.items = std::move(pairs); |
3253 | if (!varDefOnly) { | 3411 | if (!varDefOnly) { |
@@ -3286,7 +3444,7 @@ private: | |||
3286 | destruct.valueVar.clear(); | 3444 | destruct.valueVar.clear(); |
3287 | } | 3445 | } |
3288 | } | 3446 | } |
3289 | destructs.push_back(destruct); | 3447 | destructs.push_back(std::move(destruct)); |
3290 | } | 3448 | } |
3291 | } | 3449 | } |
3292 | } else { | 3450 | } else { |
@@ -4205,12 +4363,22 @@ private: | |||
4205 | 4363 | ||
4206 | std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { | 4364 | std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { |
4207 | if (checkUpValueFuncAvailable(exp)) { | 4365 | if (checkUpValueFuncAvailable(exp)) { |
4366 | auto block = exp->new_ptr<Block_t>(); | ||
4367 | if (auto sVal = simpleSingleValueFrom(exp)) { | ||
4368 | if (auto doNode = sVal->value.as<Do_t>()) { | ||
4369 | if (auto blk = doNode->body->content.as<Block_t>()) { | ||
4370 | block->statements.dup(blk->statements); | ||
4371 | } else { | ||
4372 | block->statements.push_back(doNode->body->content.to<Statement_t>()); | ||
4373 | } | ||
4374 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); | ||
4375 | } | ||
4376 | } | ||
4208 | auto returnNode = exp->new_ptr<Return_t>(); | 4377 | auto returnNode = exp->new_ptr<Return_t>(); |
4209 | returnNode->explicitReturn = false; | 4378 | returnNode->explicitReturn = false; |
4210 | auto returnList = exp->new_ptr<ExpListLow_t>(); | 4379 | auto returnList = exp->new_ptr<ExpListLow_t>(); |
4211 | returnList->exprs.push_back(exp); | 4380 | returnList->exprs.push_back(exp); |
4212 | returnNode->valueList.set(returnList); | 4381 | returnNode->valueList.set(returnList); |
4213 | auto block = exp->new_ptr<Block_t>(); | ||
4214 | auto stmt = exp->new_ptr<Statement_t>(); | 4382 | auto stmt = exp->new_ptr<Statement_t>(); |
4215 | stmt->content.set(returnNode); | 4383 | stmt->content.set(returnNode); |
4216 | block->statements.push_back(stmt); | 4384 | block->statements.push_back(stmt); |
@@ -4287,7 +4455,9 @@ private: | |||
4287 | return false; | 4455 | return false; |
4288 | }; | 4456 | }; |
4289 | switch (usage) { | 4457 | switch (usage) { |
4290 | case ExpUsage::Common: YUEE("AST node mismatch", x); return; | 4458 | case ExpUsage::Common: |
4459 | YUEE("AST node mismatch", x); | ||
4460 | return; | ||
4291 | case ExpUsage::Return: | 4461 | case ExpUsage::Return: |
4292 | case ExpUsage::Closure: { | 4462 | case ExpUsage::Closure: { |
4293 | prepareValue(); | 4463 | prepareValue(); |
@@ -4410,6 +4580,7 @@ private: | |||
4410 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; | 4580 | 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; | 4581 | 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; | 4582 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; |
4583 | 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; | 4584 | 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; | 4585 | 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; | 4586 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; |
@@ -4729,11 +4900,7 @@ private: | |||
4729 | auto newBody = x->new_ptr<Body_t>(); | 4900 | auto newBody = x->new_ptr<Body_t>(); |
4730 | newBody->content.set(followingBlock); | 4901 | newBody->content.set(followingBlock); |
4731 | { | 4902 | { |
4732 | auto doNode = x->new_ptr<Do_t>(); | 4903 | 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); | 4904 | auto [funcName, args] = std::move(*result); |
4738 | str_list finalArgs; | 4905 | str_list finalArgs; |
4739 | for (const auto& arg : args) { | 4906 | for (const auto& arg : args) { |
@@ -4741,9 +4908,13 @@ private: | |||
4741 | finalArgs.push_back(arg); | 4908 | finalArgs.push_back(arg); |
4742 | } | 4909 | } |
4743 | } | 4910 | } |
4744 | newBlock->statements.push_back(toAst<Statement_t>(funcName + ' ' + join(finalArgs, ","sv), x)); | 4911 | 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); | 4912 | 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); | 4913 | auto invokArgs = ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back()); |
4914 | if (finalArgs.empty()) { | ||
4915 | invokArgs->args.clear(); | ||
4916 | } | ||
4917 | invokArgs->args.dup(newInvoke->args); | ||
4747 | transformBlock(newBlock, out, usage, assignList, isRoot); | 4918 | transformBlock(newBlock, out, usage, assignList, isRoot); |
4748 | return; | 4919 | return; |
4749 | } | 4920 | } |
@@ -4820,6 +4991,38 @@ private: | |||
4820 | newBlock->statements.push_back(toAst<Statement_t>("if "s + okVar + " then return ... else error ..."s, x)); | 4991 | newBlock->statements.push_back(toAst<Statement_t>("if "s + okVar + " then return ... else error ..."s, x)); |
4821 | transformBlock(newBlock, out, usage, assignList, isRoot); | 4992 | transformBlock(newBlock, out, usage, assignList, isRoot); |
4822 | return; | 4993 | return; |
4994 | } else if (auto expListAssign = stmt->content.as<ExpListAssign_t>(); | ||
4995 | expListAssign && expListAssign->action && expListAssign->action.is<SubBackcall_t>()) { | ||
4996 | auto x = *nodes.begin(); | ||
4997 | auto newBlock = x->new_ptr<Block_t>(); | ||
4998 | if (it != nodes.begin()) { | ||
4999 | for (auto i = nodes.begin(); i != it; ++i) { | ||
5000 | newBlock->statements.push_back(*i); | ||
5001 | } | ||
5002 | } | ||
5003 | auto doBackcall = static_cast<SubBackcall_t*>(expListAssign->action.get()); | ||
5004 | auto backcall = expListAssign->new_ptr<Backcall_t>(); | ||
5005 | auto argsDef = backcall->new_ptr<FnArgsDef_t>(); | ||
5006 | try { | ||
5007 | auto defList = toAst<FnArgDefList_t>(YueFormat{}.toString(expListAssign->expList), expListAssign->expList); | ||
5008 | argsDef->defList.set(defList); | ||
5009 | } catch (const std::exception&) { | ||
5010 | throw CompileError("backcall syntax error", backcall); | ||
5011 | } | ||
5012 | backcall->argsDef.set(argsDef); | ||
5013 | backcall->arrow.set(doBackcall->arrow); | ||
5014 | backcall->value.set(doBackcall->value); | ||
5015 | auto newStmt = backcall->new_ptr<Statement_t>(); | ||
5016 | newStmt->content.set(backcall); | ||
5017 | newStmt->comments.dup(stmt->comments); | ||
5018 | newStmt->appendix.set(stmt->appendix); | ||
5019 | newBlock->statements.push_back(newStmt); | ||
5020 | auto ait = it; | ||
5021 | for (auto i = ++ait; i != nodes.end(); ++i) { | ||
5022 | newBlock->statements.push_back(*i); | ||
5023 | } | ||
5024 | transformBlock(newBlock, out, usage, assignList, isRoot); | ||
5025 | return; | ||
4823 | } | 5026 | } |
4824 | if (auto local = stmt->content.as<Local_t>()) { | 5027 | if (auto local = stmt->content.as<Local_t>()) { |
4825 | if (!local->collected) { | 5028 | if (!local->collected) { |
@@ -4991,36 +5194,45 @@ private: | |||
4991 | if (!nodes.empty()) { | 5194 | if (!nodes.empty()) { |
4992 | str_list temp; | 5195 | str_list temp; |
4993 | for (auto node : nodes) { | 5196 | for (auto node : nodes) { |
4994 | currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None; | 5197 | auto transformNode = [&]() { |
4995 | transformStatement(static_cast<Statement_t*>(node), temp); | 5198 | currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None; |
4996 | if (isRoot && !_rootDefs.empty()) { | 5199 | transformStatement(static_cast<Statement_t*>(node), temp); |
4997 | auto last = std::move(temp.back()); | 5200 | if (isRoot && !_rootDefs.empty()) { |
4998 | temp.pop_back(); | 5201 | auto last = std::move(temp.back()); |
4999 | temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); | 5202 | temp.pop_back(); |
5000 | _rootDefs.clear(); | 5203 | temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); |
5001 | temp.push_back(std::move(last)); | 5204 | _rootDefs.clear(); |
5002 | } | 5205 | temp.push_back(std::move(last)); |
5003 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { | 5206 | } |
5004 | auto rit = ++temp.rbegin(); | 5207 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { |
5005 | if (rit != temp.rend() && !rit->empty()) { | 5208 | auto rit = ++temp.rbegin(); |
5006 | auto index = std::string::npos; | 5209 | if (rit != temp.rend() && !rit->empty()) { |
5007 | if (_config.reserveLineNumber) { | 5210 | auto index = std::string::npos; |
5008 | index = rit->rfind(" -- "sv); | 5211 | if (_config.reserveLineNumber) { |
5009 | } else { | 5212 | index = rit->rfind(" -- "sv); |
5010 | index = rit->find_last_not_of('\n'); | 5213 | } else { |
5011 | if (index != std::string::npos) index++; | 5214 | index = rit->find_last_not_of('\n'); |
5012 | } | 5215 | 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 | } | 5216 | } |
5019 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | 5217 | if (index != std::string::npos) { |
5020 | rit->insert(index, ";"sv); | 5218 | auto ending = rit->substr(0, index); |
5219 | auto ind = ending.find_last_of(" \t\n"sv); | ||
5220 | if (ind != std::string::npos) { | ||
5221 | ending = ending.substr(ind + 1); | ||
5222 | } | ||
5223 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | ||
5224 | rit->insert(index, ";"sv); | ||
5225 | } | ||
5021 | } | 5226 | } |
5022 | } | 5227 | } |
5023 | } | 5228 | } |
5229 | }; | ||
5230 | if (_config.lax) { | ||
5231 | try { | ||
5232 | transformNode(); | ||
5233 | } catch (const CompileError&) { } | ||
5234 | } else { | ||
5235 | transformNode(); | ||
5024 | } | 5236 | } |
5025 | } | 5237 | } |
5026 | out.push_back(join(temp)); | 5238 | out.push_back(join(temp)); |
@@ -5229,18 +5441,29 @@ private: | |||
5229 | auto macroLit = macro->decl.to<MacroLit_t>(); | 5441 | auto macroLit = macro->decl.to<MacroLit_t>(); |
5230 | auto argsDef = macroLit->argsDef.get(); | 5442 | auto argsDef = macroLit->argsDef.get(); |
5231 | str_list newArgs; | 5443 | str_list newArgs; |
5444 | str_list argChecks; | ||
5445 | bool hasCheck = false; | ||
5232 | if (argsDef) { | 5446 | if (argsDef) { |
5233 | for (auto def_ : argsDef->definitions.objects()) { | 5447 | for (auto def_ : argsDef->definitions.objects()) { |
5234 | auto def = static_cast<FnArgDef_t*>(def_); | 5448 | auto def = static_cast<FnArgDef_t*>(def_); |
5235 | if (def->name.is<SelfItem_t>()) { | 5449 | if (def->name.is<SelfItem_t>()) { |
5236 | throw CompileError("self name is not supported for macro function argument"sv, def->name); | 5450 | throw CompileError("self name is not supported for macro function argument"sv, def->name); |
5237 | } else { | 5451 | } else { |
5452 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
5453 | if (def->label) { | ||
5454 | hasCheck = true; | ||
5455 | const auto& astName = argChecks.emplace_back(_parser.toString(def->label)); | ||
5456 | if (!_parser.hasAST(astName)) { | ||
5457 | throw CompileError("invalid AST name"sv, def->label); | ||
5458 | } | ||
5459 | } else { | ||
5460 | argChecks.emplace_back(); | ||
5461 | } | ||
5238 | std::string defVal; | 5462 | std::string defVal; |
5239 | if (def->defaultValue) { | 5463 | if (def->defaultValue) { |
5240 | defVal = _parser.toString(def->defaultValue); | 5464 | defVal = _parser.toString(def->defaultValue); |
5241 | Utils::trim(defVal); | 5465 | Utils::trim(defVal); |
5242 | defVal.insert(0, "=[==========["sv); | 5466 | defVal = '=' + Utils::toLuaDoubleString(defVal); |
5243 | defVal.append("]==========]"sv); | ||
5244 | } | 5467 | } |
5245 | newArgs.emplace_back(_parser.toString(def->name) + defVal); | 5468 | newArgs.emplace_back(_parser.toString(def->name) + defVal); |
5246 | } | 5469 | } |
@@ -5248,6 +5471,14 @@ private: | |||
5248 | if (argsDef->varArg) { | 5471 | if (argsDef->varArg) { |
5249 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); | 5472 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); |
5250 | } | 5473 | } |
5474 | if (argsDef->label) { | ||
5475 | hasCheck = true; | ||
5476 | const auto& astName = _parser.toString(argsDef->label); | ||
5477 | if (!_parser.hasAST(astName)) { | ||
5478 | throw CompileError("invalid AST name"sv, argsDef->label); | ||
5479 | } | ||
5480 | argChecks.emplace_back("..."s + astName); | ||
5481 | } | ||
5251 | } | 5482 | } |
5252 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); | 5483 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); |
5253 | auto chunkName = "=(macro "s + macroName + ')'; | 5484 | auto chunkName = "=(macro "s + macroName + ')'; |
@@ -5278,6 +5509,24 @@ private: | |||
5278 | throw CompileError("failed to generate macro function\n"s + err, macroLit); | 5509 | throw CompileError("failed to generate macro function\n"s + err, macroLit); |
5279 | } // cur true macro | 5510 | } // cur true macro |
5280 | lua_remove(L, -2); // cur macro | 5511 | lua_remove(L, -2); // cur macro |
5512 | if (hasCheck) { | ||
5513 | lua_createtable(L, 0, 0); // cur macro checks | ||
5514 | int i = 1; | ||
5515 | for (const auto& check : argChecks) { | ||
5516 | if (check.empty()) { | ||
5517 | lua_pushboolean(L, 0); | ||
5518 | lua_rawseti(L, -2, i); | ||
5519 | } else { | ||
5520 | lua_pushlstring(L, check.c_str(), check.size()); | ||
5521 | lua_rawseti(L, -2, i); | ||
5522 | } | ||
5523 | i++; | ||
5524 | } | ||
5525 | lua_createtable(L, 2, 0); // cur macro checks macrotab | ||
5526 | lua_insert(L, -3); // cur macrotab macro checks | ||
5527 | lua_rawseti(L, -3, 1); // macrotab[1] = checks, cur macrotab macro | ||
5528 | lua_rawseti(L, -2, 2); // macrotab[2] = macro, cur macrotab | ||
5529 | } // cur macro | ||
5281 | if (exporting && _config.exporting && !_config.module.empty()) { | 5530 | if (exporting && _config.exporting && !_config.module.empty()) { |
5282 | pushModuleTable(_config.module); // cur macro module | 5531 | pushModuleTable(_config.module); // cur macro module |
5283 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name | 5532 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name |
@@ -5352,6 +5601,9 @@ private: | |||
5352 | case id<While_t>(): | 5601 | case id<While_t>(): |
5353 | transformWhileInPlace(static_cast<While_t*>(value), out); | 5602 | transformWhileInPlace(static_cast<While_t*>(value), out); |
5354 | return; | 5603 | return; |
5604 | case id<Repeat_t>(): | ||
5605 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out); | ||
5606 | return; | ||
5355 | case id<For_t>(): | 5607 | case id<For_t>(): |
5356 | transformForInPlace(static_cast<For_t*>(value), out); | 5608 | transformForInPlace(static_cast<For_t*>(value), out); |
5357 | return; | 5609 | return; |
@@ -5423,6 +5675,7 @@ private: | |||
5423 | bool checkExistence = false; | 5675 | bool checkExistence = false; |
5424 | std::string name; | 5676 | std::string name; |
5425 | std::string assignSelf; | 5677 | std::string assignSelf; |
5678 | ast_ptr<false, ExpListAssign_t> assignment; | ||
5426 | }; | 5679 | }; |
5427 | std::list<ArgItem> argItems; | 5680 | std::list<ArgItem> argItems; |
5428 | str_list temp; | 5681 | str_list temp; |
@@ -5432,7 +5685,11 @@ private: | |||
5432 | auto def = static_cast<FnArgDef_t*>(_def); | 5685 | auto def = static_cast<FnArgDef_t*>(_def); |
5433 | auto& arg = argItems.emplace_back(); | 5686 | auto& arg = argItems.emplace_back(); |
5434 | switch (def->name->get_id()) { | 5687 | switch (def->name->get_id()) { |
5435 | case id<Variable_t>(): arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); break; | 5688 | case id<Variable_t>(): { |
5689 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
5690 | arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); | ||
5691 | break; | ||
5692 | } | ||
5436 | case id<SelfItem_t>(): { | 5693 | case id<SelfItem_t>(): { |
5437 | assignSelf = true; | 5694 | assignSelf = true; |
5438 | if (def->op) { | 5695 | if (def->op) { |
@@ -5473,6 +5730,22 @@ private: | |||
5473 | } | 5730 | } |
5474 | break; | 5731 | break; |
5475 | } | 5732 | } |
5733 | case id<TableLit_t>(): { | ||
5734 | arg.name = getUnusedName("_arg_"sv); | ||
5735 | auto simpleValue = def->new_ptr<SimpleValue_t>(); | ||
5736 | simpleValue->value.set(def->name); | ||
5737 | auto asmt = assignmentFrom(newExp(simpleValue, def), toAst<Exp_t>(arg.name, def), def); | ||
5738 | arg.assignment = asmt; | ||
5739 | break; | ||
5740 | } | ||
5741 | case id<SimpleTable_t>(): { | ||
5742 | arg.name = getUnusedName("_arg_"sv); | ||
5743 | auto value = def->new_ptr<Value_t>(); | ||
5744 | value->item.set(def->name); | ||
5745 | auto asmt = assignmentFrom(newExp(value, def), toAst<Exp_t>(arg.name, def), def); | ||
5746 | arg.assignment = asmt; | ||
5747 | break; | ||
5748 | } | ||
5476 | default: YUEE("AST node mismatch", def->name.get()); break; | 5749 | default: YUEE("AST node mismatch", def->name.get()); break; |
5477 | } | 5750 | } |
5478 | forceAddToScope(arg.name); | 5751 | forceAddToScope(arg.name); |
@@ -5491,6 +5764,14 @@ private: | |||
5491 | _buf << indent() << "end"sv << nll(def); | 5764 | _buf << indent() << "end"sv << nll(def); |
5492 | temp.back() = clearBuf(); | 5765 | temp.back() = clearBuf(); |
5493 | } | 5766 | } |
5767 | if (arg.assignment) { | ||
5768 | auto names = getArgDestructureList(arg.assignment); | ||
5769 | for (const auto& name : names) { | ||
5770 | forceAddToScope(name); | ||
5771 | } | ||
5772 | temp.emplace_back(indent() + "local "s + join(names, ", "sv) + nll(def)); | ||
5773 | transformAssignment(arg.assignment, temp); | ||
5774 | } | ||
5494 | if (varNames.empty()) | 5775 | if (varNames.empty()) |
5495 | varNames = arg.name; | 5776 | varNames = arg.name; |
5496 | else | 5777 | else |
@@ -5571,6 +5852,45 @@ private: | |||
5571 | } | 5852 | } |
5572 | } | 5853 | } |
5573 | 5854 | ||
5855 | bool transformChainEndWithSlice(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | ||
5856 | auto x = chainList.front(); | ||
5857 | if (ast_is<Slice_t>(chainList.back())) { | ||
5858 | auto comp = x->new_ptr<Comprehension_t>(); | ||
5859 | { | ||
5860 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
5861 | for (auto item : chainList) { | ||
5862 | chainValue->items.push_back(item); | ||
5863 | } | ||
5864 | auto itemVar = getUnusedName("_item_"sv); | ||
5865 | auto expCode = YueFormat{}.toString(chainValue); | ||
5866 | auto compCode = '[' + itemVar + " for "s + itemVar + " in *"s + expCode + ']'; | ||
5867 | comp.set(toAst<Comprehension_t>(compCode, x)); | ||
5868 | } | ||
5869 | switch (usage) { | ||
5870 | case ExpUsage::Assignment: { | ||
5871 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
5872 | simpleValue->value.set(comp); | ||
5873 | auto exp = newExp(simpleValue, x); | ||
5874 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
5875 | assignment->expList.set(assignList); | ||
5876 | auto assign = x->new_ptr<Assign_t>(); | ||
5877 | assign->values.push_back(exp); | ||
5878 | assignment->action.set(assign); | ||
5879 | transformAssignment(assignment, out); | ||
5880 | break; | ||
5881 | } | ||
5882 | case ExpUsage::Return: | ||
5883 | transformComprehension(comp, out, ExpUsage::Return); | ||
5884 | break; | ||
5885 | default: | ||
5886 | transformComprehension(comp, out, ExpUsage::Closure); | ||
5887 | break; | ||
5888 | } | ||
5889 | return true; | ||
5890 | } | ||
5891 | return false; | ||
5892 | } | ||
5893 | |||
5574 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | 5894 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { |
5575 | auto x = chainList.front(); | 5895 | auto x = chainList.front(); |
5576 | if (ast_is<ExistentialOp_t>(chainList.back())) { | 5896 | if (ast_is<ExistentialOp_t>(chainList.back())) { |
@@ -6088,7 +6408,7 @@ private: | |||
6088 | case id<ColonChainItem_t>(): | 6408 | case id<ColonChainItem_t>(): |
6089 | case id<Exp_t>(): | 6409 | case id<Exp_t>(): |
6090 | if (_withVars.empty()) { | 6410 | if (_withVars.empty()) { |
6091 | throw CompileError("short dot/colon and indexing syntax must be called within a with block"sv, x); | 6411 | throw CompileError("short dot/colon/indexing syntax must be called within a with block"sv, x); |
6092 | } else { | 6412 | } else { |
6093 | temp.push_back(_withVars.top()); | 6413 | temp.push_back(_withVars.top()); |
6094 | } | 6414 | } |
@@ -6234,6 +6554,93 @@ private: | |||
6234 | } | 6554 | } |
6235 | return; | 6555 | return; |
6236 | } | 6556 | } |
6557 | break; | ||
6558 | } | ||
6559 | case id<ReversedIndex_t>(): { | ||
6560 | auto rIndex = static_cast<ReversedIndex_t*>(*it); | ||
6561 | auto current = it; | ||
6562 | auto prevChain = x->new_ptr<ChainValue_t>(); | ||
6563 | for (auto i = chainList.begin(); i != current; ++i) { | ||
6564 | prevChain->items.push_back(*i); | ||
6565 | } | ||
6566 | auto var = singleVariableFrom(prevChain, AccessType::None); | ||
6567 | if (!var.empty() && isLocal(var)) { | ||
6568 | auto indexNode = toAst<Exp_t>('#' + var, rIndex); | ||
6569 | if (rIndex->modifier) { | ||
6570 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
6571 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
6572 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
6573 | indexNode->opValues.push_back(opValue); | ||
6574 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
6575 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
6576 | } | ||
6577 | prevChain->items.push_back(indexNode); | ||
6578 | auto next = current; | ||
6579 | ++next; | ||
6580 | for (auto i = next; i != chainList.end(); ++i) { | ||
6581 | prevChain->items.push_back(*i); | ||
6582 | } | ||
6583 | if (usage == ExpUsage::Assignment) { | ||
6584 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
6585 | assignment->expList.set(assignList); | ||
6586 | auto assign = x->new_ptr<Assign_t>(); | ||
6587 | assign->values.push_back(newExp(prevChain, x)); | ||
6588 | assignment->action.set(assign); | ||
6589 | transformAssignment(assignment, out); | ||
6590 | return; | ||
6591 | } | ||
6592 | transformChainValue(prevChain, out, usage, assignList); | ||
6593 | return; | ||
6594 | } else { | ||
6595 | auto itemVar = getUnusedName("_item_"sv); | ||
6596 | auto asmt = assignmentFrom(toAst<Exp_t>(itemVar, x), newExp(prevChain, x), x); | ||
6597 | auto stmt1 = x->new_ptr<Statement_t>(); | ||
6598 | stmt1->content.set(asmt); | ||
6599 | auto newChain = x->new_ptr<ChainValue_t>(); | ||
6600 | newChain->items.push_back(toAst<Callable_t>(itemVar, x)); | ||
6601 | auto indexNode = toAst<Exp_t>('#' + itemVar, rIndex); | ||
6602 | if (rIndex->modifier) { | ||
6603 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
6604 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
6605 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
6606 | indexNode->opValues.push_back(opValue); | ||
6607 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
6608 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
6609 | } | ||
6610 | newChain->items.push_back(indexNode); | ||
6611 | auto next = current; | ||
6612 | ++next; | ||
6613 | for (auto i = next; i != chainList.end(); ++i) { | ||
6614 | newChain->items.push_back(*i); | ||
6615 | } | ||
6616 | auto expList = x->new_ptr<ExpList_t>(); | ||
6617 | expList->exprs.push_back(newExp(newChain, x)); | ||
6618 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
6619 | expListAssign->expList.set(expList); | ||
6620 | auto stmt2 = x->new_ptr<Statement_t>(); | ||
6621 | stmt2->content.set(expListAssign); | ||
6622 | auto block = x->new_ptr<Block_t>(); | ||
6623 | block->statements.push_back(stmt1); | ||
6624 | block->statements.push_back(stmt2); | ||
6625 | auto body = x->new_ptr<Body_t>(); | ||
6626 | body->content.set(block); | ||
6627 | auto doNode = x->new_ptr<Do_t>(); | ||
6628 | doNode->body.set(body); | ||
6629 | if (usage == ExpUsage::Assignment) { | ||
6630 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
6631 | assignment->expList.set(assignList); | ||
6632 | auto assign = x->new_ptr<Assign_t>(); | ||
6633 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
6634 | sVal->value.set(doNode); | ||
6635 | assign->values.push_back(newExp(sVal, x)); | ||
6636 | assignment->action.set(assign); | ||
6637 | transformAssignment(assignment, out); | ||
6638 | return; | ||
6639 | } | ||
6640 | transformDo(doNode, out, usage); | ||
6641 | return; | ||
6642 | } | ||
6643 | break; | ||
6237 | } | 6644 | } |
6238 | } | 6645 | } |
6239 | } | 6646 | } |
@@ -6418,7 +6825,7 @@ private: | |||
6418 | } | 6825 | } |
6419 | } | 6826 | } |
6420 | } | 6827 | } |
6421 | int len = lua_objlen(L, -1); | 6828 | int len = static_cast<int>(lua_objlen(L, -1)); |
6422 | lua_pushnil(L); // cur nil | 6829 | lua_pushnil(L); // cur nil |
6423 | for (int i = len; i >= 1; i--) { | 6830 | for (int i = len; i >= 1; i--) { |
6424 | lua_pop(L, 1); // cur | 6831 | lua_pop(L, 1); // cur |
@@ -6430,7 +6837,25 @@ private: | |||
6430 | break; | 6837 | break; |
6431 | } | 6838 | } |
6432 | } | 6839 | } |
6433 | if (!lua_isfunction(L, -1)) { | 6840 | str_list checks; |
6841 | if (lua_istable(L, -1)) { | ||
6842 | lua_rawgeti(L, -1, 1); // cur macrotab checks | ||
6843 | int len = static_cast<int>(lua_objlen(L, -1)); | ||
6844 | for (int i = 1; i <= len; i++) { | ||
6845 | lua_rawgeti(L, -1, i); | ||
6846 | if (lua_toboolean(L, -1) == 0) { | ||
6847 | checks.emplace_back(); | ||
6848 | } else { | ||
6849 | size_t str_len = 0; | ||
6850 | auto str = lua_tolstring(L, -1, &str_len); | ||
6851 | checks.emplace_back(std::string{str, str_len}); | ||
6852 | } | ||
6853 | lua_pop(L, 1); | ||
6854 | } | ||
6855 | lua_pop(L, 1); | ||
6856 | lua_rawgeti(L, -1, 2); // cur macrotab macroFunc | ||
6857 | lua_remove(L, -2); // cur macroFunc | ||
6858 | } else if (!lua_isfunction(L, -1)) { | ||
6434 | auto code = expandBuiltinMacro(macroName, x); | 6859 | auto code = expandBuiltinMacro(macroName, x); |
6435 | if (!code.empty()) return code; | 6860 | if (!code.empty()) return code; |
6436 | if (macroName == "is_ast"sv) { | 6861 | if (macroName == "is_ast"sv) { |
@@ -6475,11 +6900,34 @@ private: | |||
6475 | } // cur macroFunc | 6900 | } // cur macroFunc |
6476 | pushYue("pcall"sv); // cur macroFunc pcall | 6901 | pushYue("pcall"sv); // cur macroFunc pcall |
6477 | lua_insert(L, -2); // cur pcall macroFunc | 6902 | lua_insert(L, -2); // cur pcall macroFunc |
6478 | if (!lua_checkstack(L, argStrs.size())) { | 6903 | if (!lua_checkstack(L, static_cast<int>(argStrs.size()))) { |
6479 | throw CompileError("too much macro params"s, x); | 6904 | throw CompileError("too much macro params"s, x); |
6480 | } | 6905 | } |
6906 | auto checkIt = checks.begin(); | ||
6907 | node_container::const_iterator argIt; | ||
6908 | if (args) { | ||
6909 | argIt = args->begin(); | ||
6910 | } | ||
6481 | for (const auto& arg : argStrs) { | 6911 | for (const auto& arg : argStrs) { |
6912 | if (checkIt != checks.end()) { | ||
6913 | if (checkIt->empty()) { | ||
6914 | ++checkIt; | ||
6915 | } else { | ||
6916 | if ((*checkIt)[0] == '.') { | ||
6917 | auto astName = checkIt->substr(3); | ||
6918 | if (!_parser.match(astName, arg)) { | ||
6919 | throw CompileError("expecting \""s + astName + "\", AST mismatch"s, *argIt); | ||
6920 | } | ||
6921 | } else { | ||
6922 | if (!_parser.match(*checkIt, arg)) { | ||
6923 | throw CompileError("expecting \""s + *checkIt + "\", AST mismatch"s, *argIt); | ||
6924 | } | ||
6925 | ++checkIt; | ||
6926 | } | ||
6927 | } | ||
6928 | } | ||
6482 | lua_pushlstring(L, arg.c_str(), arg.size()); | 6929 | lua_pushlstring(L, arg.c_str(), arg.size()); |
6930 | ++argIt; | ||
6483 | } // cur pcall macroFunc args... | 6931 | } // cur pcall macroFunc args... |
6484 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; | 6932 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; |
6485 | if (!success) { // cur err | 6933 | if (!success) { // cur err |
@@ -6609,14 +7057,14 @@ private: | |||
6609 | } else { | 7057 | } else { |
6610 | if (!codes.empty()) { | 7058 | if (!codes.empty()) { |
6611 | if (isBlock) { | 7059 | if (isBlock) { |
6612 | info = _parser.parse<BlockEnd_t>(codes); | 7060 | info = _parser.parse<BlockEnd_t>(codes, false); |
6613 | if (info.error) { | 7061 | if (info.error) { |
6614 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); | 7062 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); |
6615 | } | 7063 | } |
6616 | } else { | 7064 | } else { |
6617 | info = _parser.parse<Exp_t>(codes); | 7065 | info = _parser.parse<Exp_t>(codes, false); |
6618 | if (!info.node && allowBlockMacroReturn) { | 7066 | if (!info.node && allowBlockMacroReturn) { |
6619 | info = _parser.parse<BlockEnd_t>(codes); | 7067 | info = _parser.parse<BlockEnd_t>(codes, false); |
6620 | if (info.error) { | 7068 | if (info.error) { |
6621 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); | 7069 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); |
6622 | } | 7070 | } |
@@ -6752,6 +7200,9 @@ private: | |||
6752 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | 7200 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { |
6753 | return; | 7201 | return; |
6754 | } | 7202 | } |
7203 | if (transformChainEndWithSlice(chainList, out, usage, assignList)) { | ||
7204 | return; | ||
7205 | } | ||
6755 | transformChainList(chainList, out, usage, assignList); | 7206 | transformChainList(chainList, out, usage, assignList); |
6756 | } | 7207 | } |
6757 | 7208 | ||
@@ -7153,7 +7604,7 @@ private: | |||
7153 | try { | 7604 | try { |
7154 | unsigned long long value = std::stoull(binaryPart, nullptr, 2); | 7605 | unsigned long long value = std::stoull(binaryPart, nullptr, 2); |
7155 | numStr = std::to_string(value); | 7606 | numStr = std::to_string(value); |
7156 | } catch (const std::exception& e) { | 7607 | } catch (const std::exception&) { |
7157 | throw CompileError("invalid binary literal"sv, num); | 7608 | throw CompileError("invalid binary literal"sv, num); |
7158 | } | 7609 | } |
7159 | } else if (getLuaTarget(num) < 502) { | 7610 | } else if (getLuaTarget(num) < 502) { |
@@ -7859,6 +8310,11 @@ private: | |||
7859 | } | 8310 | } |
7860 | 8311 | ||
7861 | bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { | 8312 | bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { |
8313 | enum class NumState { | ||
8314 | Unknown, | ||
8315 | Positive, | ||
8316 | Negtive | ||
8317 | }; | ||
7862 | auto x = nameList; | 8318 | auto x = nameList; |
7863 | str_list temp; | 8319 | str_list temp; |
7864 | str_list vars; | 8320 | str_list vars; |
@@ -7925,15 +8381,35 @@ private: | |||
7925 | for (auto item : chainList) { | 8381 | for (auto item : chainList) { |
7926 | chain->items.push_back(item); | 8382 | chain->items.push_back(item); |
7927 | } | 8383 | } |
7928 | std::string startValue("1"sv); | 8384 | std::string startValue; |
8385 | NumState startStatus = NumState::Unknown; | ||
7929 | if (auto exp = slice->startValue.as<Exp_t>()) { | 8386 | if (auto exp = slice->startValue.as<Exp_t>()) { |
7930 | transformExp(exp, temp, ExpUsage::Closure); | 8387 | transformExp(exp, temp, ExpUsage::Closure); |
8388 | if (temp.back().at(0) == '-') { | ||
8389 | if (_parser.match<Num_t>(temp.back().substr(1))) { | ||
8390 | startStatus = NumState::Negtive; | ||
8391 | } | ||
8392 | } else { | ||
8393 | if (_parser.match<Num_t>(temp.back())) { | ||
8394 | startStatus = NumState::Positive; | ||
8395 | } | ||
8396 | } | ||
7931 | startValue = std::move(temp.back()); | 8397 | startValue = std::move(temp.back()); |
7932 | temp.pop_back(); | 8398 | temp.pop_back(); |
7933 | } | 8399 | } |
7934 | std::string stopValue; | 8400 | std::string stopValue; |
8401 | NumState stopStatus = NumState::Unknown; | ||
7935 | if (auto exp = slice->stopValue.as<Exp_t>()) { | 8402 | if (auto exp = slice->stopValue.as<Exp_t>()) { |
7936 | transformExp(exp, temp, ExpUsage::Closure); | 8403 | transformExp(exp, temp, ExpUsage::Closure); |
8404 | if (temp.back().at(0) == '-') { | ||
8405 | if (_parser.match<Num_t>(temp.back().substr(1))) { | ||
8406 | stopStatus = NumState::Negtive; | ||
8407 | } | ||
8408 | } else { | ||
8409 | if (_parser.match<Num_t>(temp.back())) { | ||
8410 | stopStatus = NumState::Positive; | ||
8411 | } | ||
8412 | } | ||
7937 | stopValue = std::move(temp.back()); | 8413 | stopValue = std::move(temp.back()); |
7938 | temp.pop_back(); | 8414 | temp.pop_back(); |
7939 | } | 8415 | } |
@@ -7955,8 +8431,33 @@ private: | |||
7955 | transformChainValue(chain, temp, ExpUsage::Closure); | 8431 | transformChainValue(chain, temp, ExpUsage::Closure); |
7956 | _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); | 8432 | _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); |
7957 | } | 8433 | } |
8434 | if (startValue.empty()) { | ||
8435 | startValue = "1"s; | ||
8436 | startStatus = NumState::Positive; | ||
8437 | } | ||
8438 | std::string minVar; | ||
8439 | if (startStatus != NumState::Positive) { | ||
8440 | std::string prefix; | ||
8441 | if (!extraScope && !inClosure && needScope) { | ||
8442 | extraScope = true; | ||
8443 | prefix = indent() + "do"s + nll(x); | ||
8444 | pushScope(); | ||
8445 | } | ||
8446 | minVar = getUnusedName("_min_"sv); | ||
8447 | varBefore.push_back(minVar); | ||
8448 | if (startStatus == NumState::Negtive) { | ||
8449 | _buf << prefix << indent() << "local "sv << minVar << " = "sv << "#"sv << listVar << " + "sv << startValue << " + 1"sv << nll(nameList); | ||
8450 | } else { | ||
8451 | _buf << prefix << indent() << "local "sv << minVar << " = "sv << startValue << nll(nameList); | ||
8452 | } | ||
8453 | } | ||
8454 | bool defaultStop = false; | ||
8455 | if (stopValue.empty()) { | ||
8456 | stopValue = "#"s + listVar; | ||
8457 | defaultStop = true; | ||
8458 | } | ||
7958 | std::string maxVar; | 8459 | std::string maxVar; |
7959 | if (!stopValue.empty()) { | 8460 | if (stopStatus != NumState::Positive) { |
7960 | std::string prefix; | 8461 | std::string prefix; |
7961 | if (!extraScope && !inClosure && needScope) { | 8462 | if (!extraScope && !inClosure && needScope) { |
7962 | extraScope = true; | 8463 | extraScope = true; |
@@ -7965,14 +8466,45 @@ private: | |||
7965 | } | 8466 | } |
7966 | maxVar = getUnusedName("_max_"sv); | 8467 | maxVar = getUnusedName("_max_"sv); |
7967 | varBefore.push_back(maxVar); | 8468 | varBefore.push_back(maxVar); |
7968 | _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); | 8469 | if (stopStatus == NumState::Negtive) { |
8470 | _buf << indent() << "local "sv << maxVar << " = "sv << "#"sv << listVar << " + "sv << stopValue << " + 1"sv << nll(nameList); | ||
8471 | } else { | ||
8472 | _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); | ||
8473 | } | ||
8474 | } | ||
8475 | if (startStatus == NumState::Unknown) { | ||
8476 | _buf << indent() << minVar << " = "sv << minVar << " < 0 and #"sv << listVar << " + "sv << minVar << " + 1 or "sv << minVar << nll(nameList); | ||
8477 | } | ||
8478 | if (!defaultStop && stopStatus == NumState::Unknown) { | ||
8479 | _buf << indent() << maxVar << " = "sv << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " + 1 or "sv << maxVar << nll(nameList); | ||
7969 | } | 8480 | } |
7970 | _buf << indent() << "for "sv << indexVar << " = "sv; | 8481 | _buf << indent() << "for "sv << indexVar << " = "sv; |
7971 | _buf << startValue << ", "sv; | 8482 | if (startValue.empty()) { |
8483 | _buf << "1"sv; | ||
8484 | } else { | ||
8485 | switch (startStatus) { | ||
8486 | case NumState::Unknown: | ||
8487 | case NumState::Negtive: | ||
8488 | _buf << minVar; | ||
8489 | break; | ||
8490 | case NumState::Positive: | ||
8491 | _buf << startValue; | ||
8492 | break; | ||
8493 | } | ||
8494 | } | ||
8495 | _buf << ", "sv; | ||
7972 | if (stopValue.empty()) { | 8496 | if (stopValue.empty()) { |
7973 | _buf << "#"sv << listVar; | 8497 | _buf << "#"sv << listVar; |
7974 | } else { | 8498 | } else { |
7975 | _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " or "sv << maxVar; | 8499 | switch (stopStatus) { |
8500 | case NumState::Unknown: | ||
8501 | case NumState::Negtive: | ||
8502 | _buf << maxVar; | ||
8503 | break; | ||
8504 | case NumState::Positive: | ||
8505 | _buf << stopValue; | ||
8506 | break; | ||
8507 | } | ||
7976 | } | 8508 | } |
7977 | if (!stepValue.empty()) { | 8509 | if (!stepValue.empty()) { |
7978 | _buf << ", "sv << stepValue; | 8510 | _buf << ", "sv << stepValue; |
@@ -8012,7 +8544,7 @@ private: | |||
8012 | pushScope(); | 8544 | pushScope(); |
8013 | for (const auto& var : vars) forceAddToScope(var); | 8545 | for (const auto& var : vars) forceAddToScope(var); |
8014 | for (const auto& var : varAfter) addToScope(var); | 8546 | for (const auto& var : varAfter) addToScope(var); |
8015 | if (!varConstAfter.empty()) markVarConst(varConstAfter); | 8547 | if (!varConstAfter.empty()) markVarLocalConst(varConstAfter); |
8016 | if (!destructPairs.empty()) { | 8548 | if (!destructPairs.empty()) { |
8017 | temp.clear(); | 8549 | temp.clear(); |
8018 | for (auto& pair : destructPairs) { | 8550 | for (auto& pair : destructPairs) { |
@@ -8097,7 +8629,7 @@ private: | |||
8097 | _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : ", "s + step) << " do"sv << nll(var); | 8629 | _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : ", "s + step) << " do"sv << nll(var); |
8098 | pushScope(); | 8630 | pushScope(); |
8099 | forceAddToScope(varName); | 8631 | forceAddToScope(varName); |
8100 | markVarConst(varName); | 8632 | markVarLocalConst(varName); |
8101 | out.push_back(clearBuf()); | 8633 | out.push_back(clearBuf()); |
8102 | } | 8634 | } |
8103 | 8635 | ||
@@ -8105,26 +8637,59 @@ private: | |||
8105 | transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); | 8637 | transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); |
8106 | } | 8638 | } |
8107 | 8639 | ||
8108 | void transform_plain_body(ast_node* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8640 | void transform_plain_body(ast_node* bodyOrStmt, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
8109 | switch (body->get_id()) { | 8641 | switch (bodyOrStmt->get_id()) { |
8110 | case id<Block_t>(): | 8642 | case id<Block_t>(): |
8111 | transformBlock(static_cast<Block_t*>(body), out, usage, assignList); | 8643 | transformBlock(static_cast<Block_t*>(bodyOrStmt), out, usage, assignList); |
8112 | break; | 8644 | break; |
8113 | case id<Statement_t>(): { | 8645 | case id<Statement_t>(): { |
8114 | auto newBlock = body->new_ptr<Block_t>(); | 8646 | auto newBlock = bodyOrStmt->new_ptr<Block_t>(); |
8115 | newBlock->statements.push_back(body); | 8647 | newBlock->statements.push_back(bodyOrStmt); |
8116 | transformBlock(newBlock, out, usage, assignList); | 8648 | transformBlock(newBlock, out, usage, assignList); |
8117 | break; | 8649 | break; |
8118 | } | 8650 | } |
8119 | default: YUEE("AST node mismatch", body); break; | 8651 | default: YUEE("AST node mismatch", bodyOrStmt); break; |
8120 | } | 8652 | } |
8121 | } | 8653 | } |
8122 | 8654 | ||
8123 | bool hasContinueStatement(ast_node* body) { | 8655 | enum class BreakLoopType { |
8124 | return traversal::Stop == body->traverse([&](ast_node* node) { | 8656 | None = 0, |
8657 | Break = 1, | ||
8658 | BreakWithValue = 1 << 1, | ||
8659 | Continue = 1 << 2 | ||
8660 | }; | ||
8661 | |||
8662 | bool hasBreak(uint32_t breakLoopType) const { | ||
8663 | return (breakLoopType & int(BreakLoopType::Break)) != 0; | ||
8664 | } | ||
8665 | |||
8666 | bool hasBreakWithValue(uint32_t breakLoopType) const { | ||
8667 | return (breakLoopType & int(BreakLoopType::BreakWithValue)) != 0; | ||
8668 | } | ||
8669 | |||
8670 | bool hasContinue(uint32_t breakLoopType) const { | ||
8671 | return (breakLoopType & int(BreakLoopType::Continue)) != 0; | ||
8672 | } | ||
8673 | |||
8674 | uint32_t getBreakLoopType(ast_node* body, const std::string& varBWV) { | ||
8675 | uint32_t type = 0; | ||
8676 | body->traverse([&](ast_node* node) { | ||
8125 | if (auto stmt = ast_cast<Statement_t>(node)) { | 8677 | if (auto stmt = ast_cast<Statement_t>(node)) { |
8126 | if (stmt->content.is<BreakLoop_t>()) { | 8678 | if (auto breakLoop = stmt->content.as<BreakLoop_t>()) { |
8127 | return _parser.toString(stmt->content) == "continue"sv ? traversal::Stop : traversal::Return; | 8679 | if (breakLoop->type.is<Continue_t>()) { |
8680 | type |= int(BreakLoopType::Continue); | ||
8681 | return traversal::Return; | ||
8682 | } else { | ||
8683 | if (breakLoop->value) { | ||
8684 | if (varBWV.empty()) { | ||
8685 | throw CompileError("break with a value is not allowed here"sv, breakLoop->value); | ||
8686 | } | ||
8687 | type |= int(BreakLoopType::BreakWithValue); | ||
8688 | breakLoop->varBWV = varBWV; | ||
8689 | } else { | ||
8690 | type |= int(BreakLoopType::Break); | ||
8691 | } | ||
8692 | } | ||
8128 | } else if (auto expList = expListFrom(stmt)) { | 8693 | } else if (auto expList = expListFrom(stmt)) { |
8129 | BLOCK_START | 8694 | BLOCK_START |
8130 | auto value = singleValueFrom(expList); | 8695 | auto value = singleValueFrom(expList); |
@@ -8135,40 +8700,30 @@ private: | |||
8135 | switch (sVal->get_id()) { | 8700 | switch (sVal->get_id()) { |
8136 | case id<With_t>(): { | 8701 | case id<With_t>(): { |
8137 | auto withNode = static_cast<With_t*>(sVal); | 8702 | auto withNode = static_cast<With_t*>(sVal); |
8138 | if (hasContinueStatement(withNode->body)) { | 8703 | type |= getBreakLoopType(withNode->body, varBWV); |
8139 | return traversal::Stop; | 8704 | return traversal::Return; |
8140 | } | ||
8141 | break; | ||
8142 | } | 8705 | } |
8143 | case id<Do_t>(): { | 8706 | case id<Do_t>(): { |
8144 | auto doNode = static_cast<Do_t*>(sVal); | 8707 | auto doNode = static_cast<Do_t*>(sVal); |
8145 | if (hasContinueStatement(doNode->body)) { | 8708 | type |= getBreakLoopType(doNode->body, varBWV); |
8146 | return traversal::Stop; | 8709 | return traversal::Return; |
8147 | } | ||
8148 | break; | ||
8149 | } | 8710 | } |
8150 | case id<If_t>(): { | 8711 | case id<If_t>(): { |
8151 | auto ifNode = static_cast<If_t*>(sVal); | 8712 | auto ifNode = static_cast<If_t*>(sVal); |
8152 | for (auto n : ifNode->nodes.objects()) { | 8713 | for (auto n : ifNode->nodes.objects()) { |
8153 | if (hasContinueStatement(n)) { | 8714 | type |= getBreakLoopType(n, varBWV); |
8154 | return traversal::Stop; | ||
8155 | } | ||
8156 | } | 8715 | } |
8157 | break; | 8716 | return traversal::Return; |
8158 | } | 8717 | } |
8159 | case id<Switch_t>(): { | 8718 | case id<Switch_t>(): { |
8160 | auto switchNode = static_cast<Switch_t*>(sVal); | 8719 | auto switchNode = static_cast<Switch_t*>(sVal); |
8161 | for (auto branch : switchNode->branches.objects()) { | 8720 | for (auto branch : switchNode->branches.objects()) { |
8162 | if (hasContinueStatement(static_cast<SwitchCase_t*>(branch)->body)) { | 8721 | type |= getBreakLoopType(static_cast<SwitchCase_t*>(branch)->body, varBWV); |
8163 | return traversal::Stop; | ||
8164 | } | ||
8165 | } | 8722 | } |
8166 | if (switchNode->lastBranch) { | 8723 | if (switchNode->lastBranch) { |
8167 | if (hasContinueStatement(switchNode->lastBranch)) { | 8724 | type |= getBreakLoopType(switchNode->lastBranch, varBWV); |
8168 | return traversal::Stop; | ||
8169 | } | ||
8170 | } | 8725 | } |
8171 | break; | 8726 | return traversal::Return; |
8172 | } | 8727 | } |
8173 | } | 8728 | } |
8174 | BLOCK_END | 8729 | BLOCK_END |
@@ -8182,6 +8737,7 @@ private: | |||
8182 | } | 8737 | } |
8183 | return traversal::Return; | 8738 | return traversal::Return; |
8184 | }); | 8739 | }); |
8740 | return type; | ||
8185 | } | 8741 | } |
8186 | 8742 | ||
8187 | void addDoToLastLineReturn(ast_node* body) { | 8743 | void addDoToLastLineReturn(ast_node* body) { |
@@ -8205,10 +8761,10 @@ private: | |||
8205 | } | 8761 | } |
8206 | } | 8762 | } |
8207 | 8763 | ||
8208 | void transformLoopBody(ast_node* body, str_list& out, const std::string& appendContent, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8764 | void transformLoopBody(ast_node* body, str_list& out, uint32_t breakLoopType, ExpUsage usage, ExpList_t* assignList = nullptr) { |
8209 | str_list temp; | 8765 | str_list temp; |
8210 | bool extraDo = false; | 8766 | bool extraDo = false; |
8211 | bool withContinue = hasContinueStatement(body); | 8767 | bool withContinue = hasContinue(breakLoopType); |
8212 | int target = getLuaTarget(body); | 8768 | int target = getLuaTarget(body); |
8213 | std::string extraLabel; | 8769 | std::string extraLabel; |
8214 | if (withContinue) { | 8770 | if (withContinue) { |
@@ -8217,7 +8773,7 @@ private: | |||
8217 | if (!block->statements.empty()) { | 8773 | if (!block->statements.empty()) { |
8218 | auto stmt = static_cast<Statement_t*>(block->statements.back()); | 8774 | auto stmt = static_cast<Statement_t*>(block->statements.back()); |
8219 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { | 8775 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { |
8220 | extraDo = _parser.toString(breakLoop) == "break"sv; | 8776 | extraDo = breakLoop->type.is<Break_t>(); |
8221 | } | 8777 | } |
8222 | } | 8778 | } |
8223 | } | 8779 | } |
@@ -8250,9 +8806,6 @@ private: | |||
8250 | popScope(); | 8806 | popScope(); |
8251 | _buf << indent() << "end"sv << nll(body); | 8807 | _buf << indent() << "end"sv << nll(body); |
8252 | } | 8808 | } |
8253 | if (!appendContent.empty()) { | ||
8254 | _buf << indent() << appendContent; | ||
8255 | } | ||
8256 | _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); | 8809 | _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); |
8257 | popScope(); | 8810 | popScope(); |
8258 | _buf << indent() << "until true"sv << nlr(body); | 8811 | _buf << indent() << "until true"sv << nlr(body); |
@@ -8262,14 +8815,9 @@ private: | |||
8262 | temp.push_back(clearBuf()); | 8815 | temp.push_back(clearBuf()); |
8263 | _continueVars.pop(); | 8816 | _continueVars.pop(); |
8264 | } else { | 8817 | } else { |
8265 | if (!appendContent.empty()) { | ||
8266 | temp.push_back(indent() + appendContent); | ||
8267 | } | ||
8268 | temp.push_back(extraLabel); | 8818 | temp.push_back(extraLabel); |
8269 | _continueVars.pop(); | 8819 | _continueVars.pop(); |
8270 | } | 8820 | } |
8271 | } else if (!appendContent.empty()) { | ||
8272 | temp.back().append(indent() + appendContent); | ||
8273 | } | 8821 | } |
8274 | out.push_back(join(temp)); | 8822 | out.push_back(join(temp)); |
8275 | } | 8823 | } |
@@ -8277,8 +8825,9 @@ private: | |||
8277 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { | 8825 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { |
8278 | str_list temp; | 8826 | str_list temp; |
8279 | bool extraDo = false; | 8827 | bool extraDo = false; |
8280 | auto body = repeatNode->body->content.get(); | 8828 | auto body = repeatNode->body.get(); |
8281 | bool withContinue = hasContinueStatement(body); | 8829 | auto breakLoopType = getBreakLoopType(body, Empty); |
8830 | bool withContinue = hasContinue(breakLoopType); | ||
8282 | std::string conditionVar; | 8831 | std::string conditionVar; |
8283 | std::string extraLabel; | 8832 | std::string extraLabel; |
8284 | ast_ptr<false, ExpListAssign_t> condAssign; | 8833 | ast_ptr<false, ExpListAssign_t> condAssign; |
@@ -8289,7 +8838,7 @@ private: | |||
8289 | if (!block->statements.empty()) { | 8838 | if (!block->statements.empty()) { |
8290 | auto stmt = static_cast<Statement_t*>(block->statements.back()); | 8839 | auto stmt = static_cast<Statement_t*>(block->statements.back()); |
8291 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { | 8840 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { |
8292 | extraDo = _parser.toString(breakLoop) == "break"sv; | 8841 | extraDo = breakLoop->type.is<Break_t>(); |
8293 | } | 8842 | } |
8294 | } | 8843 | } |
8295 | } | 8844 | } |
@@ -8352,7 +8901,8 @@ private: | |||
8352 | void transformFor(For_t* forNode, str_list& out) { | 8901 | void transformFor(For_t* forNode, str_list& out) { |
8353 | str_list temp; | 8902 | str_list temp; |
8354 | transformForHead(forNode, temp); | 8903 | transformForHead(forNode, temp); |
8355 | transformLoopBody(forNode->body, temp, Empty, ExpUsage::Common); | 8904 | auto breakLoopType = getBreakLoopType(forNode->body, Empty); |
8905 | transformLoopBody(forNode->body, temp, breakLoopType, ExpUsage::Common); | ||
8356 | popScope(); | 8906 | popScope(); |
8357 | out.push_back(join(temp) + indent() + "end"s + nlr(forNode)); | 8907 | out.push_back(join(temp) + indent() + "end"s + nlr(forNode)); |
8358 | } | 8908 | } |
@@ -8363,13 +8913,24 @@ private: | |||
8363 | addToScope(accum); | 8913 | addToScope(accum); |
8364 | std::string len = getUnusedName("_len_"sv); | 8914 | std::string len = getUnusedName("_len_"sv); |
8365 | addToScope(len); | 8915 | addToScope(len); |
8366 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forNode); | 8916 | auto breakLoopType = getBreakLoopType(forNode->body, accum); |
8917 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(forNode); | ||
8918 | out.emplace_back(clearBuf()); | ||
8367 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); | 8919 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); |
8368 | out.push_back(clearBuf()); | 8920 | auto& lenAssign = out.emplace_back(clearBuf()); |
8369 | transformForHead(forNode, out); | 8921 | transformForHead(forNode, out); |
8370 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 8922 | if (hasBreakWithValue(breakLoopType)) { |
8371 | auto lenLine = len + " = "s + len + " + 1"s + nlr(forNode->body); | 8923 | lenAssign.clear(); |
8372 | transformLoopBody(forNode->body, out, lenLine, ExpUsage::Assignment, expList); | 8924 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Common); |
8925 | } else { | ||
8926 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | ||
8927 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forNode->body); | ||
8928 | expList->followStmt = followStmt.get(); | ||
8929 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
8930 | if (!expList->followStmtProcessed) { | ||
8931 | lenAssign.clear(); | ||
8932 | } | ||
8933 | } | ||
8373 | popScope(); | 8934 | popScope(); |
8374 | out.push_back(indent() + "end"s + nlr(forNode)); | 8935 | out.push_back(indent() + "end"s + nlr(forNode)); |
8375 | return accum; | 8936 | return accum; |
@@ -8448,7 +9009,8 @@ private: | |||
8448 | void transformForEach(ForEach_t* forEach, str_list& out) { | 9009 | void transformForEach(ForEach_t* forEach, str_list& out) { |
8449 | str_list temp; | 9010 | str_list temp; |
8450 | bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false); | 9011 | bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false); |
8451 | transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common); | 9012 | auto breakLoopType = getBreakLoopType(forEach->body, Empty); |
9013 | transformLoopBody(forEach->body, temp, breakLoopType, ExpUsage::Common); | ||
8452 | popScope(); | 9014 | popScope(); |
8453 | out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach)); | 9015 | out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach)); |
8454 | if (extraScoped) { | 9016 | if (extraScoped) { |
@@ -8463,13 +9025,24 @@ private: | |||
8463 | addToScope(accum); | 9025 | addToScope(accum); |
8464 | std::string len = getUnusedName("_len_"sv); | 9026 | std::string len = getUnusedName("_len_"sv); |
8465 | addToScope(len); | 9027 | addToScope(len); |
8466 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); | 9028 | auto breakLoopType = getBreakLoopType(forEach->body, accum); |
9029 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(forEach); | ||
9030 | out.emplace_back(clearBuf()); | ||
8467 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); | 9031 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); |
8468 | out.push_back(clearBuf()); | 9032 | auto& lenAssign = out.emplace_back(clearBuf()); |
8469 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); | 9033 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); |
8470 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 9034 | if (hasBreakWithValue(breakLoopType)) { |
8471 | auto lenLine = len + " = "s + len + " + 1"s + nlr(forEach->body); | 9035 | lenAssign.clear(); |
8472 | transformLoopBody(forEach->body, out, lenLine, ExpUsage::Assignment, expList); | 9036 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Common); |
9037 | } else { | ||
9038 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | ||
9039 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forEach->body); | ||
9040 | expList->followStmt = followStmt.get(); | ||
9041 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
9042 | if (!expList->followStmtProcessed) { | ||
9043 | lenAssign.clear(); | ||
9044 | } | ||
9045 | } | ||
8473 | popScope(); | 9046 | popScope(); |
8474 | out.push_back(indent() + "end"s + nlr(forEach)); | 9047 | out.push_back(indent() + "end"s + nlr(forEach)); |
8475 | return accum; | 9048 | return accum; |
@@ -8653,12 +9226,64 @@ private: | |||
8653 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); | 9226 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); |
8654 | } | 9227 | } |
8655 | 9228 | ||
9229 | void transformYAMLMultiline(YAMLMultiline_t* multiline, str_list& out) { | ||
9230 | std::optional<std::string> indent; | ||
9231 | str_list temp; | ||
9232 | for (auto line_ : multiline->lines.objects()) { | ||
9233 | auto line = static_cast<YAMLLine_t*>(line_); | ||
9234 | auto indentStr = _parser.toString(line->indent); | ||
9235 | if (!indent) { | ||
9236 | indent = indentStr; | ||
9237 | } | ||
9238 | if (std::string_view{indentStr.c_str(), indent.value().size()} != indent.value()) { | ||
9239 | throw CompileError("inconsistent indent"sv, line); | ||
9240 | } | ||
9241 | indentStr = indentStr.substr(indent.value().size()); | ||
9242 | str_list segs; | ||
9243 | bool firstSeg = true; | ||
9244 | for (auto seg_ : line->segments.objects()) { | ||
9245 | auto content = static_cast<YAMLLineContent_t*>(seg_)->content.get(); | ||
9246 | switch (content->get_id()) { | ||
9247 | case id<YAMLLineInner_t>(): { | ||
9248 | auto seqStr = _parser.toString(content); | ||
9249 | Utils::replace(seqStr, "\\#"sv, "#"sv); | ||
9250 | if (firstSeg) { | ||
9251 | firstSeg = false; | ||
9252 | seqStr.insert(0, indentStr); | ||
9253 | } | ||
9254 | segs.push_back(Utils::toLuaDoubleString(seqStr)); | ||
9255 | break; | ||
9256 | } | ||
9257 | case id<Exp_t>(): { | ||
9258 | if (firstSeg) { | ||
9259 | firstSeg = false; | ||
9260 | if (!indentStr.empty()) { | ||
9261 | segs.push_back(Utils::toLuaDoubleString(indentStr)); | ||
9262 | } | ||
9263 | } | ||
9264 | transformExp(static_cast<Exp_t*>(content), segs, ExpUsage::Closure); | ||
9265 | segs.back() = globalVar("tostring"sv, content, AccessType::Read) + '(' + segs.back() + ')'; | ||
9266 | break; | ||
9267 | } | ||
9268 | default: YUEE("AST node mismatch", content); break; | ||
9269 | } | ||
9270 | } | ||
9271 | temp.push_back(join(segs, " .. "sv)); | ||
9272 | } | ||
9273 | auto str = join(temp, " .. '\\n' .. "sv); | ||
9274 | Utils::replace(str, "\" .. '\\n' .. \""sv, "\\n"sv); | ||
9275 | Utils::replace(str, "\" .. '\\n'"sv, "\\n\""sv); | ||
9276 | Utils::replace(str, "'\\n' .. \""sv, "\"\\n"sv); | ||
9277 | out.push_back(str); | ||
9278 | } | ||
9279 | |||
8656 | void transformString(String_t* string, str_list& out) { | 9280 | void transformString(String_t* string, str_list& out) { |
8657 | auto str = string->str.get(); | 9281 | auto str = string->str.get(); |
8658 | switch (str->get_id()) { | 9282 | switch (str->get_id()) { |
8659 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; | 9283 | 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; | 9284 | 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; | 9285 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; |
9286 | case id<YAMLMultiline_t>(): transformYAMLMultiline(static_cast<YAMLMultiline_t*>(str), out); break; | ||
8662 | default: YUEE("AST node mismatch", str); break; | 9287 | default: YUEE("AST node mismatch", str); break; |
8663 | } | 9288 | } |
8664 | } | 9289 | } |
@@ -8840,7 +9465,7 @@ private: | |||
8840 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get); | 9465 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get); |
8841 | for (const auto& name : names) { | 9466 | for (const auto& name : names) { |
8842 | forceAddToScope(name.first); | 9467 | forceAddToScope(name.first); |
8843 | markVarConst(name.first); | 9468 | markVarLocalConst(name.first); |
8844 | varDefs.push_back(name.first); | 9469 | varDefs.push_back(name.first); |
8845 | classConstVars.push_back(name.first); | 9470 | classConstVars.push_back(name.first); |
8846 | } | 9471 | } |
@@ -8854,7 +9479,7 @@ private: | |||
8854 | for (const auto& item : destruct.items) { | 9479 | for (const auto& item : destruct.items) { |
8855 | if (!item.targetVar.empty()) { | 9480 | if (!item.targetVar.empty()) { |
8856 | forceAddToScope(item.targetVar); | 9481 | forceAddToScope(item.targetVar); |
8857 | markVarConst(item.targetVar); | 9482 | markVarLocalConst(item.targetVar); |
8858 | varDefs.push_back(item.targetVar); | 9483 | varDefs.push_back(item.targetVar); |
8859 | classConstVars.push_back(item.targetVar); | 9484 | classConstVars.push_back(item.targetVar); |
8860 | } | 9485 | } |
@@ -9236,11 +9861,11 @@ private: | |||
9236 | std::string withVar; | 9861 | std::string withVar; |
9237 | bool needScope = !currentScope().lastStatement && !returnValue; | 9862 | bool needScope = !currentScope().lastStatement && !returnValue; |
9238 | bool extraScope = false; | 9863 | bool extraScope = false; |
9239 | if (with->assigns) { | 9864 | if (with->assign) { |
9240 | auto vars = getAssignVars(with); | 9865 | auto vars = getAssignVars(with); |
9241 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { | 9866 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { |
9242 | if (with->assigns->values.objects().size() == 1) { | 9867 | if (with->assign->values.objects().size() == 1) { |
9243 | auto var = singleVariableFrom(with->assigns->values.objects().front(), AccessType::Read); | 9868 | auto var = singleVariableFrom(with->assign->values.objects().front(), AccessType::Read); |
9244 | if (!var.empty() && isLocal(var)) { | 9869 | if (!var.empty() && isLocal(var)) { |
9245 | withVar = var; | 9870 | withVar = var; |
9246 | } | 9871 | } |
@@ -9250,7 +9875,7 @@ private: | |||
9250 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 9875 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
9251 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); | 9876 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); |
9252 | auto assign = x->new_ptr<Assign_t>(); | 9877 | auto assign = x->new_ptr<Assign_t>(); |
9253 | assign->values.push_back(with->assigns->values.objects().front()); | 9878 | assign->values.push_back(with->assign->values.objects().front()); |
9254 | assignment->action.set(assign); | 9879 | assignment->action.set(assign); |
9255 | if (needScope) { | 9880 | if (needScope) { |
9256 | extraScope = true; | 9881 | extraScope = true; |
@@ -9264,7 +9889,7 @@ private: | |||
9264 | auto assign = x->new_ptr<Assign_t>(); | 9889 | auto assign = x->new_ptr<Assign_t>(); |
9265 | assign->values.push_back(toAst<Exp_t>(withVar, x)); | 9890 | assign->values.push_back(toAst<Exp_t>(withVar, x)); |
9266 | bool skipFirst = true; | 9891 | bool skipFirst = true; |
9267 | for (auto value : with->assigns->values.objects()) { | 9892 | for (auto value : with->assign->values.objects()) { |
9268 | if (skipFirst) { | 9893 | if (skipFirst) { |
9269 | skipFirst = false; | 9894 | skipFirst = false; |
9270 | continue; | 9895 | continue; |
@@ -9277,7 +9902,7 @@ private: | |||
9277 | withVar = vars.front(); | 9902 | withVar = vars.front(); |
9278 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 9903 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
9279 | assignment->expList.set(with->valueList); | 9904 | assignment->expList.set(with->valueList); |
9280 | assignment->action.set(with->assigns); | 9905 | assignment->action.set(with->assign); |
9281 | if (needScope) { | 9906 | if (needScope) { |
9282 | extraScope = true; | 9907 | extraScope = true; |
9283 | temp.push_back(indent() + "do"s + nll(with)); | 9908 | temp.push_back(indent() + "do"s + nll(with)); |
@@ -9355,15 +9980,57 @@ private: | |||
9355 | } | 9980 | } |
9356 | } | 9981 | } |
9357 | _withVars.push(withVar); | 9982 | _withVars.push(withVar); |
9983 | std::string breakWithVar; | ||
9984 | if (assignList || returnValue) { | ||
9985 | auto breakLoopType = getBreakLoopType(with->body, withVar); | ||
9986 | if (hasBreakWithValue(breakLoopType)) { | ||
9987 | breakWithVar = withVar; | ||
9988 | } | ||
9989 | } | ||
9358 | if (with->eop) { | 9990 | if (with->eop) { |
9359 | auto ifNode = x->new_ptr<If_t>(); | 9991 | auto ifNode = x->new_ptr<If_t>(); |
9360 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); | 9992 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); |
9361 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); | 9993 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); |
9362 | ifNode->nodes.push_back(with->body); | 9994 | ifNode->nodes.push_back(with->body); |
9363 | transformIf(ifNode, temp, ExpUsage::Common); | 9995 | if (breakWithVar.empty()) { |
9996 | transformIf(ifNode, temp, ExpUsage::Common); | ||
9997 | } else { | ||
9998 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
9999 | simpleValue->value.set(ifNode); | ||
10000 | auto exp = newExp(simpleValue, x); | ||
10001 | auto expList = x->new_ptr<ExpList_t>(); | ||
10002 | expList->exprs.push_back(exp); | ||
10003 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
10004 | expListAssign->expList.set(expList); | ||
10005 | auto stmt = x->new_ptr<Statement_t>(); | ||
10006 | stmt->content.set(expListAssign); | ||
10007 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); | ||
10008 | auto block = x->new_ptr<Block_t>(); | ||
10009 | block->statements.push_back(stmt); | ||
10010 | repeatNode->body.set(block); | ||
10011 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
10012 | sVal->value.set(repeatNode); | ||
10013 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | ||
10014 | transformAssignment(asmt, temp); | ||
10015 | } | ||
9364 | } else { | 10016 | } else { |
9365 | bool transformed = false; | 10017 | bool transformed = false; |
9366 | if (!extraScope && assignList) { | 10018 | if (!breakWithVar.empty()) { |
10019 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); | ||
10020 | auto block = x->new_ptr<Block_t>(); | ||
10021 | if (auto blk = with->body.as<Block_t>()) { | ||
10022 | block->statements.dup(blk->statements); | ||
10023 | } else { | ||
10024 | auto stmt = with->body.to<Statement_t>(); | ||
10025 | block->statements.push_back(stmt); | ||
10026 | } | ||
10027 | repeatNode->body.set(block); | ||
10028 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
10029 | sVal->value.set(repeatNode); | ||
10030 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | ||
10031 | transformAssignment(asmt, temp); | ||
10032 | transformed = true; | ||
10033 | } else if (!extraScope && assignList) { | ||
9367 | if (auto block = with->body.as<Block_t>()) { | 10034 | if (auto block = with->body.as<Block_t>()) { |
9368 | if (!block->statements.empty()) { | 10035 | if (!block->statements.empty()) { |
9369 | Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); | 10036 | Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); |
@@ -9428,12 +10095,18 @@ private: | |||
9428 | switch (item->get_id()) { | 10095 | switch (item->get_id()) { |
9429 | case id<ClassDecl_t>(): { | 10096 | case id<ClassDecl_t>(): { |
9430 | auto classDecl = static_cast<ClassDecl_t*>(item); | 10097 | auto classDecl = static_cast<ClassDecl_t*>(item); |
10098 | std::string varName; | ||
9431 | if (classDecl->name) { | 10099 | if (classDecl->name) { |
9432 | if (auto var = classDecl->name->item.as<Variable_t>()) { | 10100 | if (auto var = classDecl->name->item.as<Variable_t>()) { |
9433 | addGlobalVar(variableToString(var), classDecl->name->item); | 10101 | varName = variableToString(var); |
10102 | addGlobalVar(varName, var); | ||
9434 | } | 10103 | } |
9435 | } | 10104 | } |
10105 | if (varName.empty()) { | ||
10106 | throw CompileError("missing name for class", classDecl); | ||
10107 | } | ||
9436 | transformClassDecl(classDecl, out, ExpUsage::Common); | 10108 | transformClassDecl(classDecl, out, ExpUsage::Common); |
10109 | markVarGlobalConst(varName); | ||
9437 | break; | 10110 | break; |
9438 | } | 10111 | } |
9439 | case id<GlobalOp_t>(): | 10112 | case id<GlobalOp_t>(): |
@@ -9447,9 +10120,11 @@ private: | |||
9447 | auto values = global->item.to<GlobalValues_t>(); | 10120 | auto values = global->item.to<GlobalValues_t>(); |
9448 | if (values->valueList) { | 10121 | if (values->valueList) { |
9449 | auto expList = x->new_ptr<ExpList_t>(); | 10122 | auto expList = x->new_ptr<ExpList_t>(); |
10123 | str_list varNames; | ||
9450 | for (auto name : values->nameList->names.objects()) { | 10124 | for (auto name : values->nameList->names.objects()) { |
9451 | auto var = static_cast<Variable_t*>(name); | 10125 | auto var = static_cast<Variable_t*>(name); |
9452 | addGlobalVar(variableToString(var), var); | 10126 | varNames.emplace_back(variableToString(var)); |
10127 | addGlobalVar(varNames.back(), var); | ||
9453 | auto callable = x->new_ptr<Callable_t>(); | 10128 | auto callable = x->new_ptr<Callable_t>(); |
9454 | callable->item.set(name); | 10129 | callable->item.set(name); |
9455 | auto chainValue = x->new_ptr<ChainValue_t>(); | 10130 | auto chainValue = x->new_ptr<ChainValue_t>(); |
@@ -9468,10 +10143,17 @@ private: | |||
9468 | } | 10143 | } |
9469 | assignment->action.set(assign); | 10144 | assignment->action.set(assign); |
9470 | transformAssignment(assignment, out); | 10145 | transformAssignment(assignment, out); |
10146 | for (const auto& name : varNames) { | ||
10147 | markVarGlobalConst(name); | ||
10148 | } | ||
9471 | } else { | 10149 | } else { |
9472 | for (auto name : values->nameList->names.objects()) { | 10150 | for (auto name : values->nameList->names.objects()) { |
9473 | auto var = static_cast<Variable_t*>(name); | 10151 | auto var = static_cast<Variable_t*>(name); |
9474 | addGlobalVar(variableToString(var), var); | 10152 | auto varName = variableToString(var); |
10153 | addGlobalVar(varName, var); | ||
10154 | if (global->constAttrib) { | ||
10155 | markVarGlobalConst(varName); | ||
10156 | } | ||
9475 | } | 10157 | } |
9476 | } | 10158 | } |
9477 | break; | 10159 | break; |
@@ -9820,8 +10502,47 @@ private: | |||
9820 | out.push_back(join(temp)); | 10502 | out.push_back(join(temp)); |
9821 | } | 10503 | } |
9822 | 10504 | ||
9823 | void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage) { | 10505 | void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
9824 | auto x = tryNode; | 10506 | auto x = tryNode; |
10507 | if (tryNode->eop && usage == ExpUsage::Assignment) { | ||
10508 | str_list rets; | ||
10509 | pushScope(); | ||
10510 | auto okVar = getUnusedName("_ok_"sv); | ||
10511 | for (size_t i = 0; i < assignList->exprs.size(); i++) { | ||
10512 | auto retVar = getUnusedName("_ret_"sv); | ||
10513 | rets.emplace_back(retVar); | ||
10514 | addToScope(retVar); | ||
10515 | } | ||
10516 | popScope(); | ||
10517 | auto varList = join(rets, ","sv); | ||
10518 | auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x); | ||
10519 | auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front(); | ||
10520 | auto sVal = simpleSingleValueFrom(exp); | ||
10521 | auto newTry = sVal->value.to<Try_t>(); | ||
10522 | newTry->func.set(tryNode->func); | ||
10523 | newTry->catchBlock.set(tryNode->catchBlock); | ||
10524 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
10525 | assignment->expList.set(assignList); | ||
10526 | auto assign = x->new_ptr<Assign_t>(); | ||
10527 | assign->values.push_back(ifNode); | ||
10528 | assignment->action.set(assign); | ||
10529 | transformAssignment(assignment, out); | ||
10530 | return; | ||
10531 | } | ||
10532 | if (tryNode->eop && usage != ExpUsage::Common) { | ||
10533 | auto okVar = getUnusedName("_ok_"sv); | ||
10534 | auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar; | ||
10535 | auto doNode = toAst<Do_t>(code, x); | ||
10536 | auto block = doNode->body->content.to<Block_t>(); | ||
10537 | auto asmt = static_cast<Statement_t*>(block->statements.front())->content.to<ExpListAssign_t>(); | ||
10538 | auto assign = asmt->action.to<Assign_t>(); | ||
10539 | auto sVal = simpleSingleValueFrom(assign->values.back()); | ||
10540 | auto newTry = sVal->value.to<Try_t>(); | ||
10541 | newTry->func.set(tryNode->func); | ||
10542 | newTry->catchBlock.set(tryNode->catchBlock); | ||
10543 | transformDo(doNode, out, usage); | ||
10544 | return; | ||
10545 | } | ||
9825 | ast_ptr<true, Exp_t> errHandler; | 10546 | ast_ptr<true, Exp_t> errHandler; |
9826 | if (tryNode->catchBlock) { | 10547 | if (tryNode->catchBlock) { |
9827 | auto catchBlock = tryNode->catchBlock.get(); | 10548 | auto catchBlock = tryNode->catchBlock.get(); |
@@ -10133,7 +10854,7 @@ private: | |||
10133 | out.push_back(join(temp)); | 10854 | out.push_back(join(temp)); |
10134 | auto vars = getAssignVars(assignment); | 10855 | auto vars = getAssignVars(assignment); |
10135 | for (const auto& var : vars) { | 10856 | for (const auto& var : vars) { |
10136 | markVarConst(var); | 10857 | markVarLocalConst(var); |
10137 | } | 10858 | } |
10138 | } | 10859 | } |
10139 | 10860 | ||
@@ -10361,12 +11082,36 @@ private: | |||
10361 | transformAssignment(assignment, out); | 11082 | transformAssignment(assignment, out); |
10362 | if (auto var = ast_cast<Variable_t>(target)) { | 11083 | if (auto var = ast_cast<Variable_t>(target)) { |
10363 | auto moduleName = variableToString(var); | 11084 | auto moduleName = variableToString(var); |
10364 | markVarConst(moduleName); | 11085 | markVarLocalConst(moduleName); |
10365 | } else { | 11086 | } else { |
10366 | markDestructureConst(assignment); | 11087 | markDestructureConst(assignment); |
10367 | } | 11088 | } |
10368 | } | 11089 | } |
10369 | 11090 | ||
11091 | void transformImportGlobal(ImportGlobal_t* importNode, str_list& out) { | ||
11092 | auto uname = static_cast<UnicodeName_t*>(importNode->segs.front()); | ||
11093 | auto var = _parser.toString(uname); | ||
11094 | auto isNormal = _parser.match<Name_t>(var) && _parser.match<Variable_t>(var); | ||
11095 | auto varName = unicodeVariableFrom(uname); | ||
11096 | str_list temp; | ||
11097 | auto it = ++importNode->segs.objects().begin(); | ||
11098 | for (; it != importNode->segs.objects().end(); ++it) { | ||
11099 | temp.emplace_back(_parser.toString(*it)); | ||
11100 | } | ||
11101 | temp.emplace_front(var); | ||
11102 | if (isLocal(varName) || !isNormal) { | ||
11103 | temp.emplace_front("_G"s); | ||
11104 | } | ||
11105 | std::string stmt; | ||
11106 | if (importNode->target) { | ||
11107 | stmt = "const "s + _parser.toString(importNode->target) + '=' + join(temp, "."sv); | ||
11108 | } else { | ||
11109 | stmt = "const "s + temp.back() + '=' + join(temp, "."sv); | ||
11110 | } | ||
11111 | auto localAttrib = toAst<LocalAttrib_t>(stmt, importNode); | ||
11112 | transformLocalAttrib(localAttrib, out); | ||
11113 | } | ||
11114 | |||
10370 | void transformImport(Import_t* import, str_list& out) { | 11115 | void transformImport(Import_t* import, str_list& out) { |
10371 | auto content = import->content.get(); | 11116 | auto content = import->content.get(); |
10372 | switch (content->get_id()) { | 11117 | switch (content->get_id()) { |
@@ -10379,6 +11124,9 @@ private: | |||
10379 | case id<FromImport_t>(): | 11124 | case id<FromImport_t>(): |
10380 | transformFromImport(static_cast<FromImport_t*>(content), out); | 11125 | transformFromImport(static_cast<FromImport_t*>(content), out); |
10381 | break; | 11126 | break; |
11127 | case id<ImportGlobal_t>(): | ||
11128 | transformImportGlobal(static_cast<ImportGlobal_t*>(content), out); | ||
11129 | break; | ||
10382 | default: YUEE("AST node mismatch", content); break; | 11130 | default: YUEE("AST node mismatch", content); break; |
10383 | } | 11131 | } |
10384 | } | 11132 | } |
@@ -10398,15 +11146,27 @@ private: | |||
10398 | addToScope(accumVar); | 11146 | addToScope(accumVar); |
10399 | auto lenVar = getUnusedName("_len_"sv); | 11147 | auto lenVar = getUnusedName("_len_"sv); |
10400 | addToScope(lenVar); | 11148 | addToScope(lenVar); |
10401 | temp.push_back(indent() + "local "s + accumVar + " = { }"s + nll(whileNode)); | 11149 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); |
10402 | temp.push_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | 11150 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(whileNode); |
11151 | temp.emplace_back(clearBuf()); | ||
11152 | _buf << indent() << "local "s << lenVar << " = 1"s << nll(whileNode); | ||
11153 | auto& lenAssign = temp.emplace_back(clearBuf()); | ||
10403 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11154 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
10404 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11155 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
10405 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 11156 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); |
10406 | pushScope(); | 11157 | pushScope(); |
10407 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 11158 | if (hasBreakWithValue(breakLoopType)) { |
10408 | auto lenLine = lenVar + " = "s + lenVar + " + 1"s + nlr(whileNode); | 11159 | lenAssign.clear(); |
10409 | transformLoopBody(whileNode->body, temp, lenLine, ExpUsage::Assignment, assignLeft); | 11160 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); |
11161 | } else { | ||
11162 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
11163 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
11164 | assignLeft->followStmt = followStmt.get(); | ||
11165 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
11166 | if (!assignLeft->followStmtProcessed) { | ||
11167 | lenAssign.clear(); | ||
11168 | } | ||
11169 | } | ||
10410 | popScope(); | 11170 | popScope(); |
10411 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11171 | temp.push_back(indent() + "end"s + nlr(whileNode)); |
10412 | if (expList) { | 11172 | if (expList) { |
@@ -10442,15 +11202,26 @@ private: | |||
10442 | addToScope(accumVar); | 11202 | addToScope(accumVar); |
10443 | auto lenVar = getUnusedName("_len_"sv); | 11203 | auto lenVar = getUnusedName("_len_"sv); |
10444 | addToScope(lenVar); | 11204 | addToScope(lenVar); |
10445 | temp.push_back(indent() + "local "s + accumVar + " = { }"s + nll(whileNode)); | 11205 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); |
10446 | temp.push_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | 11206 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(whileNode); |
11207 | temp.emplace_back(clearBuf()); | ||
11208 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | ||
10447 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11209 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
10448 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11210 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
10449 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 11211 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); |
10450 | pushScope(); | 11212 | pushScope(); |
10451 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 11213 | if (hasBreakWithValue(breakLoopType)) { |
10452 | auto lenLine = lenVar + " = "s + lenVar + " + 1"s + nlr(whileNode); | 11214 | lenAssign.clear(); |
10453 | transformLoopBody(whileNode->body, temp, lenLine, ExpUsage::Assignment, assignLeft); | 11215 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); |
11216 | } else { | ||
11217 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
11218 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
11219 | assignLeft->followStmt = followStmt.get(); | ||
11220 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
11221 | if (!assignLeft->followStmtProcessed) { | ||
11222 | lenAssign.clear(); | ||
11223 | } | ||
11224 | } | ||
10454 | popScope(); | 11225 | popScope(); |
10455 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11226 | temp.push_back(indent() + "end"s + nlr(whileNode)); |
10456 | temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); | 11227 | temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); |
@@ -10485,9 +11256,7 @@ private: | |||
10485 | expListAssign->expList.set(expList); | 11256 | expListAssign->expList.set(expList); |
10486 | auto stmt = x->new_ptr<Statement_t>(); | 11257 | auto stmt = x->new_ptr<Statement_t>(); |
10487 | stmt->content.set(expListAssign); | 11258 | stmt->content.set(expListAssign); |
10488 | auto body = x->new_ptr<Body_t>(); | 11259 | repeat->body.set(stmt); |
10489 | body->content.set(stmt); | ||
10490 | repeat->body.set(body); | ||
10491 | transformRepeat(repeat, out); | 11260 | transformRepeat(repeat, out); |
10492 | return; | 11261 | return; |
10493 | } | 11262 | } |
@@ -10495,7 +11264,8 @@ private: | |||
10495 | pushScope(); | 11264 | pushScope(); |
10496 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11265 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
10497 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11266 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
10498 | transformLoopBody(whileNode->body, temp, Empty, ExpUsage::Common); | 11267 | auto breakLoopType = getBreakLoopType(whileNode->body, Empty); |
11268 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); | ||
10499 | popScope(); | 11269 | popScope(); |
10500 | _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode); | 11270 | _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode); |
10501 | _buf << temp.back(); | 11271 | _buf << temp.back(); |
@@ -10503,6 +11273,106 @@ private: | |||
10503 | out.push_back(clearBuf()); | 11273 | out.push_back(clearBuf()); |
10504 | } | 11274 | } |
10505 | 11275 | ||
11276 | void transformRepeatInPlace(Repeat_t* repeatNode, str_list& out, ExpList_t* expList = nullptr) { | ||
11277 | auto x = repeatNode; | ||
11278 | str_list temp; | ||
11279 | bool extraScope = false; | ||
11280 | if (expList) { | ||
11281 | if (!currentScope().lastStatement) { | ||
11282 | extraScope = true; | ||
11283 | temp.push_back(indent() + "do"s + nll(repeatNode)); | ||
11284 | pushScope(); | ||
11285 | } | ||
11286 | } | ||
11287 | auto accumVar = getUnusedName("_accum_"sv); | ||
11288 | addToScope(accumVar); | ||
11289 | auto lenVar = getUnusedName("_len_"sv); | ||
11290 | addToScope(lenVar); | ||
11291 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
11292 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(repeatNode); | ||
11293 | temp.emplace_back(clearBuf()); | ||
11294 | _buf << indent() << "local "s << lenVar << " = 1"s << nll(repeatNode); | ||
11295 | auto& lenAssign = temp.emplace_back(clearBuf()); | ||
11296 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
11297 | temp.push_back(indent() + "repeat"s + nll(repeatNode)); | ||
11298 | pushScope(); | ||
11299 | if (hasBreakWithValue(breakLoopType)) { | ||
11300 | lenAssign.clear(); | ||
11301 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
11302 | } else { | ||
11303 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
11304 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
11305 | assignLeft->followStmt = followStmt.get(); | ||
11306 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
11307 | if (!assignLeft->followStmtProcessed) { | ||
11308 | lenAssign.clear(); | ||
11309 | } | ||
11310 | } | ||
11311 | popScope(); | ||
11312 | temp.push_back(indent() + "until "s + condStr + nlr(repeatNode)); | ||
11313 | if (expList) { | ||
11314 | auto assign = x->new_ptr<Assign_t>(); | ||
11315 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); | ||
11316 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
11317 | assignment->expList.set(expList); | ||
11318 | assignment->action.set(assign); | ||
11319 | transformAssignment(assignment, temp); | ||
11320 | if (extraScope) popScope(); | ||
11321 | } else { | ||
11322 | temp.push_back(indent() + "return "s + accumVar + nlr(repeatNode)); | ||
11323 | } | ||
11324 | if (expList && extraScope) { | ||
11325 | temp.push_back(indent() + "end"s + nlr(repeatNode)); | ||
11326 | } | ||
11327 | out.push_back(join(temp)); | ||
11328 | } | ||
11329 | |||
11330 | void transformRepeatClosure(Repeat_t* repeatNode, str_list& out) { | ||
11331 | auto x = repeatNode; | ||
11332 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
11333 | simpleValue->value.set(repeatNode); | ||
11334 | if (transformAsUpValueFunc(newExp(simpleValue, x), out)) { | ||
11335 | return; | ||
11336 | } | ||
11337 | str_list temp; | ||
11338 | pushAnonFunctionScope(); | ||
11339 | pushAnonVarArg(); | ||
11340 | std::string& funcStart = temp.emplace_back(); | ||
11341 | pushScope(); | ||
11342 | auto accumVar = getUnusedName("_accum_"sv); | ||
11343 | addToScope(accumVar); | ||
11344 | auto lenVar = getUnusedName("_len_"sv); | ||
11345 | addToScope(lenVar); | ||
11346 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
11347 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(repeatNode); | ||
11348 | temp.emplace_back(clearBuf()); | ||
11349 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nll(repeatNode)); | ||
11350 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
11351 | temp.push_back(indent() + "repeat"s + nll(repeatNode)); | ||
11352 | pushScope(); | ||
11353 | if (hasBreakWithValue(breakLoopType)) { | ||
11354 | lenAssign.clear(); | ||
11355 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
11356 | } else { | ||
11357 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
11358 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
11359 | assignLeft->followStmt = followStmt.get(); | ||
11360 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
11361 | if (!assignLeft->followStmtProcessed) { | ||
11362 | lenAssign.clear(); | ||
11363 | } | ||
11364 | } | ||
11365 | popScope(); | ||
11366 | temp.push_back(indent() + "until "s + condStr + nlr(repeatNode)); | ||
11367 | temp.push_back(indent() + "return "s + accumVar + nlr(repeatNode)); | ||
11368 | popScope(); | ||
11369 | funcStart = anonFuncStart() + nll(repeatNode); | ||
11370 | temp.push_back(indent() + anonFuncEnd()); | ||
11371 | popAnonVarArg(); | ||
11372 | popFunctionScope(); | ||
11373 | out.push_back(join(temp)); | ||
11374 | } | ||
11375 | |||
10506 | void transformRepeat(Repeat_t* repeat, str_list& out) { | 11376 | void transformRepeat(Repeat_t* repeat, str_list& out) { |
10507 | str_list temp; | 11377 | str_list temp; |
10508 | pushScope(); | 11378 | pushScope(); |
@@ -10536,10 +11406,26 @@ private: | |||
10536 | pushScope(); | 11406 | pushScope(); |
10537 | } | 11407 | } |
10538 | bool extraScope = false; | 11408 | bool extraScope = false; |
11409 | if (switchNode->assignment) { | ||
11410 | if (needScope) { | ||
11411 | extraScope = true; | ||
11412 | temp.push_back(indent() + "do"s + nll(x)); | ||
11413 | pushScope(); | ||
11414 | } | ||
11415 | auto asmt = x->new_ptr<ExpListAssign_t>(); | ||
11416 | auto expList = x->new_ptr<ExpList_t>(); | ||
11417 | expList->exprs.push_back(switchNode->target); | ||
11418 | if (switchNode->assignment->expList) { | ||
11419 | expList->exprs.dup(switchNode->assignment->expList->exprs); | ||
11420 | } | ||
11421 | asmt->expList.set(expList); | ||
11422 | asmt->action.set(switchNode->assignment->assign); | ||
11423 | transformAssignment(asmt, temp); | ||
11424 | } | ||
10539 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); | 11425 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); |
10540 | if (objVar.empty() || !isLocal(objVar)) { | 11426 | if (objVar.empty() || !isLocal(objVar)) { |
10541 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { | 11427 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { |
10542 | if (needScope) { | 11428 | if (needScope && !extraScope) { |
10543 | extraScope = true; | 11429 | extraScope = true; |
10544 | temp.push_back(indent() + "do"s + nll(x)); | 11430 | temp.push_back(indent() + "do"s + nll(x)); |
10545 | pushScope(); | 11431 | pushScope(); |
@@ -10597,8 +11483,9 @@ private: | |||
10597 | } | 11483 | } |
10598 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); | 11484 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); |
10599 | pushScope(); | 11485 | pushScope(); |
10600 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), toAst<Exp_t>(objVar, branch), branch); | 11486 | auto chainValue = toAst<ChainValue_t>(objVar, branch); |
10601 | auto info = extractDestructureInfo(assignment, true, false); | 11487 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), newExp(chainValue, branch), branch); |
11488 | auto info = extractDestructureInfo(assignment, true, true); | ||
10602 | transformAssignment(assignment, temp, true); | 11489 | transformAssignment(assignment, temp, true); |
10603 | str_list conds; | 11490 | str_list conds; |
10604 | for (const auto& des : info.destructures) { | 11491 | for (const auto& des : info.destructures) { |
@@ -10608,8 +11495,31 @@ private: | |||
10608 | const auto& destruct = std::get<Destructure>(des); | 11495 | const auto& destruct = std::get<Destructure>(des); |
10609 | for (const auto& item : destruct.items) { | 11496 | for (const auto& item : destruct.items) { |
10610 | if (!item.defVal) { | 11497 | if (!item.defVal) { |
10611 | transformExp(item.target, conds, ExpUsage::Closure); | 11498 | if (!isAssignable(item.target)) { |
10612 | conds.back().append(" ~= nil"s); | 11499 | auto callable = chainValue->items.front(); |
11500 | auto chain = callable->new_ptr<ChainValue_t>(); | ||
11501 | chain->items.push_back(callable); | ||
11502 | chain->items.dup(item.structure->items); | ||
11503 | if (specialChainValue(chain) == ChainType::Common) { | ||
11504 | transformChainValue(chain, conds, ExpUsage::Closure); | ||
11505 | auto vStr = conds.back(); | ||
11506 | conds.pop_back(); | ||
11507 | transformExp(item.target, conds, ExpUsage::Closure); | ||
11508 | conds.back().append(" == "s); | ||
11509 | conds.back().append(vStr); | ||
11510 | } else { | ||
11511 | auto varName = getUnusedName("_val_"sv); | ||
11512 | auto vExp = toAst<Exp_t>(varName, chain); | ||
11513 | auto asmt = assignmentFrom(vExp, newExp(chain, chain), chain); | ||
11514 | transformAssignment(asmt, temp); | ||
11515 | transformExp(item.target, conds, ExpUsage::Closure); | ||
11516 | conds.back().append(" == "s); | ||
11517 | conds.back().append(varName); | ||
11518 | } | ||
11519 | } else { | ||
11520 | transformExp(item.target, conds, ExpUsage::Closure); | ||
11521 | conds.back().append(" ~= nil"s); | ||
11522 | } | ||
10613 | } | 11523 | } |
10614 | } | 11524 | } |
10615 | } | 11525 | } |
@@ -10907,7 +11817,7 @@ private: | |||
10907 | } | 11817 | } |
10908 | transformAssignment(assignment, temp); | 11818 | transformAssignment(assignment, temp); |
10909 | for (const auto& name : vars) { | 11819 | for (const auto& name : vars) { |
10910 | markVarConst(name); | 11820 | markVarLocalConst(name); |
10911 | } | 11821 | } |
10912 | if (localAttrib->attrib.is<CloseAttrib_t>()) { | 11822 | if (localAttrib->attrib.is<CloseAttrib_t>()) { |
10913 | str_list leftVars, rightVars; | 11823 | str_list leftVars, rightVars; |
@@ -10979,7 +11889,7 @@ private: | |||
10979 | temp.push_back(indent() + "local "s + join(leftVars, ", "sv) + " = "s + join(items, ", "sv) + nll(x)); | 11889 | temp.push_back(indent() + "local "s + join(leftVars, ", "sv) + " = "s + join(items, ", "sv) + nll(x)); |
10980 | } | 11890 | } |
10981 | for (const auto& var : vars) { | 11891 | for (const auto& var : vars) { |
10982 | markVarConst(var); | 11892 | markVarLocalConst(var); |
10983 | } | 11893 | } |
10984 | } | 11894 | } |
10985 | if (!listB->exprs.empty()) { | 11895 | if (!listB->exprs.empty()) { |
@@ -11004,18 +11914,24 @@ private: | |||
11004 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); | 11914 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); |
11005 | transformAssignment(assignment, temp); | 11915 | transformAssignment(assignment, temp); |
11006 | for (const auto& name : vars) { | 11916 | for (const auto& name : vars) { |
11007 | markVarConst(name); | 11917 | markVarLocalConst(name); |
11008 | } | 11918 | } |
11009 | } | 11919 | } |
11010 | out.push_back(join(temp)); | 11920 | out.push_back(join(temp)); |
11011 | } | 11921 | } |
11012 | 11922 | ||
11013 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { | 11923 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { |
11014 | auto keyword = _parser.toString(breakLoop); | 11924 | auto isBreak = breakLoop->type.is<Break_t>(); |
11925 | auto keyword = isBreak ? "break"s : "continue"s; | ||
11015 | if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { | 11926 | if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { |
11016 | throw CompileError(keyword + " is not inside a loop"s, breakLoop); | 11927 | throw CompileError(keyword + " is not inside a loop"s, breakLoop); |
11017 | } | 11928 | } |
11018 | if (keyword == "break"sv) { | 11929 | if (isBreak) { |
11930 | if (breakLoop->value) { | ||
11931 | auto exp = toAst<Exp_t>(breakLoop->varBWV, breakLoop->value); | ||
11932 | auto assignment = assignmentFrom(exp, breakLoop->value, breakLoop); | ||
11933 | transformAssignment(assignment, out); | ||
11934 | } | ||
11019 | out.push_back(indent() + keyword + nll(breakLoop)); | 11935 | out.push_back(indent() + keyword + nll(breakLoop)); |
11020 | return; | 11936 | return; |
11021 | } | 11937 | } |
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..01ca083 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) | TableLit | SimpleTable; |
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 | ||
1038 | ParseInfo YueParser::parse(std::string_view codes, rule& r) { | 1083 | ParseInfo 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 | ||
1093 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes) { | 1139 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes, bool lax) { |
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 | ||
1101 | bool YueParser::match(std::string_view astName, std::string_view codes) { | 1149 | bool 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 | |||
1190 | std::string toLuaDoubleString(const std::string& input) { | ||
1191 | std::string luaStr = "\""; | ||
1192 | for (char c : input) { | ||
1193 | switch (c) { | ||
1194 | case '\"': luaStr += "\\\""; break; | ||
1195 | case '\\': luaStr += "\\\\"; break; | ||
1196 | case '\n': luaStr += "\\n"; break; | ||
1197 | case '\r': luaStr += "\\r"; break; | ||
1198 | case '\t': luaStr += "\\t"; break; | ||
1199 | default: | ||
1200 | luaStr += c; | ||
1201 | break; | ||
1202 | } | ||
1203 | } | ||
1204 | luaStr += "\""; | ||
1205 | return luaStr; | ||
1206 | } | ||
1141 | } // namespace Utils | 1207 | } // namespace Utils |
1142 | 1208 | ||
1143 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { | 1209 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 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; | |||
74 | class YueParser { | 74 | class YueParser { |
75 | public: | 75 | public: |
76 | template <class AST> | 76 | template <class AST> |
77 | ParseInfo parse(std::string_view codes) { | 77 | ParseInfo parse(std::string_view codes, bool lax) { |
78 | return parse(codes, getRule<AST>()); | 78 | return parse(codes, getRule<AST>(), lax); |
79 | } | 79 | } |
80 | 80 | ||
81 | ParseInfo parse(std::string_view astName, std::string_view codes); | 81 | ParseInfo parse(std::string_view astName, std::string_view codes, bool lax); |
82 | 82 | ||
83 | template <class AST> | 83 | template <class AST> |
84 | bool match(std::string_view codes) { | 84 | bool match(std::string_view codes) { |
85 | auto rEnd = rule(getRule<AST>() >> eof()); | 85 | auto rEnd = rule(getRule<AST>() >> eof()); |
86 | return parse(codes, rEnd).node; | 86 | return parse(codes, rEnd, false).node; |
87 | } | 87 | } |
88 | 88 | ||
89 | bool match(std::string_view astName, std::string_view codes); | 89 | bool match(std::string_view astName, std::string_view codes); |
@@ -102,13 +102,14 @@ public: | |||
102 | 102 | ||
103 | protected: | 103 | protected: |
104 | YueParser(); | 104 | YueParser(); |
105 | ParseInfo parse(std::string_view codes, rule& r); | 105 | ParseInfo parse(std::string_view codes, rule& r, bool lax); |
106 | bool startWith(std::string_view codes, rule& r); | 106 | bool startWith(std::string_view codes, rule& r); |
107 | 107 | ||
108 | struct State { | 108 | struct State { |
109 | State() { | 109 | State() { |
110 | indents.push(0); | 110 | indents.push(0); |
111 | } | 111 | } |
112 | bool lax = false; | ||
112 | bool exportDefault = false; | 113 | bool exportDefault = false; |
113 | bool exportMacro = false; | 114 | bool exportMacro = false; |
114 | bool exportMetatable = false; | 115 | bool exportMetatable = false; |
@@ -119,10 +120,11 @@ protected: | |||
119 | size_t stringOpen = 0; | 120 | size_t stringOpen = 0; |
120 | std::string buffer; | 121 | std::string buffer; |
121 | std::stack<int> indents; | 122 | std::stack<int> indents; |
122 | std::stack<bool> noDoStack; | 123 | std::vector<bool> noDoStack; |
123 | std::stack<bool> noChainBlockStack; | 124 | std::vector<bool> noChainBlockStack; |
124 | std::stack<bool> noTableBlockStack; | 125 | std::vector<bool> noTableBlockStack; |
125 | std::stack<bool> noForStack; | 126 | std::vector<bool> noForStack; |
127 | std::vector<bool> noUntilStack; | ||
126 | std::unordered_set<std::string> usedNames; | 128 | std::unordered_set<std::string> usedNames; |
127 | }; | 129 | }; |
128 | 130 | ||
@@ -156,7 +158,7 @@ private: | |||
156 | NONE_AST_RULE(invalid_interpolation_error); | 158 | NONE_AST_RULE(invalid_interpolation_error); |
157 | NONE_AST_RULE(confusing_unary_not_error); | 159 | NONE_AST_RULE(confusing_unary_not_error); |
158 | NONE_AST_RULE(table_key_pair_error); | 160 | NONE_AST_RULE(table_key_pair_error); |
159 | NONE_AST_RULE(if_assignment_syntax_error); | 161 | NONE_AST_RULE(assignment_expression_syntax_error); |
160 | 162 | ||
161 | NONE_AST_RULE(inc_exp_level); | 163 | NONE_AST_RULE(inc_exp_level); |
162 | NONE_AST_RULE(dec_exp_level); | 164 | NONE_AST_RULE(dec_exp_level); |
@@ -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: | |||
444 | namespace Utils { | 459 | namespace Utils { |
445 | void replace(std::string& str, std::string_view from, std::string_view to); | 460 | void replace(std::string& str, std::string_view from, std::string_view to); |
446 | void trim(std::string& str); | 461 | void trim(std::string& str); |
462 | std::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> |