aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xdoc/docs/.vuepress/components/YueCompiler.vue83
-rwxr-xr-xdoc/docs/doc/README.md663
-rwxr-xr-xdoc/docs/zh/doc/README.md691
3 files changed, 1266 insertions, 171 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 89bd643..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
19import "yue" as :p, :to_lua 19import p, to_lua from "yue"
20 20
21-- object literals 21-- object literals
22inventory = 22inventory =
23 equipment: 23 equipment:
24 * "sword" 24 - "sword"
25 * "shield" 25 - "shield"
26 items: 26 items:
27 * name: "potion" 27 - name: "potion"
28 count: 10 28 count: 10
29 * name: "bread" 29 - name: "bread"
30 count: 3 30 count: 3
31 31
32-- list comprehension
33map = (arr, action) ->
34 [action item for item in *arr]
35
36filter = (arr, cond) ->
37 [item for item in *arr when cond item]
38
39reduce = (arr, init, action): init ->
40 init = action init, item for item in *arr
41
32-- pipe operator 42-- pipe operator
33[1, 2, 3] 43[1, 2, 3]
34 |> map (x) -> x * 2 44 |> map (x) -> x * 2
@@ -51,19 +61,29 @@ export 🌛 = "月之脚本"
51<YueDisplay> 61<YueDisplay>
52<pre> 62<pre>
53-- import syntax 63-- import syntax
54import "yue" as :p, :to_lua 64import p, to_lua from "yue"
55 65
56-- object literals 66-- object literals
57inventory = 67inventory =
58 equipment: 68 equipment:
59 * "sword" 69 - "sword"
60 * "shield" 70 - "shield"
61 items: 71 items:
62 * name: "potion" 72 - name: "potion"
63 count: 10 73 count: 10
64 * name: "bread" 74 - name: "bread"
65 count: 3 75 count: 3
66 76
77-- list comprehension
78map = (arr, action) ->
79 [action item for item in *arr]
80
81filter = (arr, cond) ->
82 [item for item in *arr when cond item]
83
84reduce = (arr, init, action): init ->
85 init = action init, item for item in *arr
86
67-- pipe operator 87-- pipe operator
68[1, 2, 3] 88[1, 2, 3]
69 |> map (x) -> x * 2 89 |> map (x) -> x * 2
@@ -132,14 +152,14 @@ export 🌛 = "月之脚本"
132 152
133&emsp;Use YueScript module in Lua: 153&emsp;Use YueScript module in Lua:
134 154
135* **Case 1** 155* **Case 1**
136Require "your_yuescript_entry.yue" in Lua. 156Require "your_yuescript_entry.yue" in Lua.
137```Lua 157```Lua
138require("yue")("your_yuescript_entry") 158require("yue")("your_yuescript_entry")
139``` 159```
140&emsp;And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. 160&emsp;And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly.
141 161
142* **Case 2** 162* **Case 2**
143Require YueScript module and rewite message by hand. 163Require YueScript module and rewite message by hand.
144```lua 164```lua
145local yue = require("yue") 165local yue = require("yue")
@@ -151,7 +171,7 @@ end, function(err)
151end) 171end)
152``` 172```
153 173
154* **Case 3** 174* **Case 3**
155Use the YueScript compiler function in Lua. 175Use the YueScript compiler function in Lua.
156```lua 176```lua
157local yue = require("yue") 177local yue = require("yue")
@@ -203,12 +223,12 @@ Usage: yue [options|files|directories] ...
203 Execute without options to enter REPL, type symbol '$' 223 Execute without options to enter REPL, type symbol '$'
204 in a single line to start/stop multi-line mode 224 in a single line to start/stop multi-line mode
205``` 225```
206&emsp;&emsp;Use cases: 226&emsp;&emsp;Use cases:
207&emsp;&emsp;Recursively compile every YueScript file with extension **.yue** under current path: **yue .** 227&emsp;&emsp;Recursively compile every YueScript file with extension **.yue** under current path: **yue .**
208&emsp;&emsp;Compile and save results to a target path: **yue -t /target/path/ .** 228&emsp;&emsp;Compile and save results to a target path: **yue -t /target/path/ .**
209&emsp;&emsp;Compile and reserve debug info: **yue -l .** 229&emsp;&emsp;Compile and reserve debug info: **yue -l .**
210&emsp;&emsp;Compile and generate minified codes: **yue -m .** 230&emsp;&emsp;Compile and generate minified codes: **yue -m .**
211&emsp;&emsp;Execute raw codes: **yue -e 'print 123'** 231&emsp;&emsp;Execute raw codes: **yue -e 'print 123'**
212&emsp;&emsp;Execute a YueScript file: **yue -e main.yue** 232&emsp;&emsp;Execute a YueScript file: **yue -e main.yue**
213 233
214## Macro 234## Macro
@@ -424,6 +444,54 @@ print "Valid enum type:", $BodyType Static
424</pre> 444</pre>
425</YueDisplay> 445</YueDisplay>
426 446
447### Argument Validation
448
449You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time.
450
451```moonscript
452macro printNumAndStr = (num `Num, str `String) -> |
453 print(
454 #{num}
455 #{str}
456 )
457
458$printNumAndStr 123, "hello"
459```
460<YueDisplay>
461<pre>
462macro printNumAndStr = (num `Num, str `String) -> |
463 print(
464 #{num}
465 #{str}
466 )
467
468$printNumAndStr 123, "hello"
469</pre>
470</YueDisplay>
471
472If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place.
473
474```moonscript
475macro printNumAndStr = (num, str) ->
476 error "expected Num as first argument" unless $is_ast Num, num
477 error "expected String as second argument" unless $is_ast String, str
478 "print(#{num}, #{str})"
479
480$printNumAndStr 123, "hello"
481```
482<YueDisplay>
483<pre>
484macro printNumAndStr = (num, str) ->
485 error "expected Num as first argument" unless $is_ast Num, num
486 error "expected String as second argument" unless $is_ast String, str
487 "print(#{num}, #{str})"
488
489$printNumAndStr 123, "hello"
490</pre>
491</YueDisplay>
492
493For more details about available AST nodes, please refer to the uppercased definitions in [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp).
494
427## Operator 495## Operator
428 496
429All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. 497All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes.
@@ -566,11 +634,26 @@ merge = {...a, ...b}
566</pre> 634</pre>
567</YueDisplay> 635</YueDisplay>
568 636
637### Table Reversed Indexing
638
639You can use the **#** operator to get the last elements of a table.
640
641```moonscript
642last = data.items[#]
643second_last = data.items[#-1]
644```
645<YueDisplay>
646<pre>
647last = data.items[#]
648second_last = data.items[#-1]
649</pre>
650</YueDisplay>
651
569### Metatable 652### Metatable
570 653
571The **<>** operator can be used as a shortcut for metatable manipulation. 654The **<>** operator can be used as a shortcut for metatable manipulation.
572 655
573* **Metatable Creation** 656* **Metatable Creation**
574Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. 657Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**.
575 658
576```moonscript 659```moonscript
@@ -606,7 +689,7 @@ close _ = &lt;close&gt;: -> print "out of scope"
606</pre> 689</pre>
607</YueDisplay> 690</YueDisplay>
608 691
609* **Metatable Accessing** 692* **Metatable Accessing**
610Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. 693Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**.
611 694
612```moonscript 695```moonscript
@@ -630,7 +713,7 @@ print tb.item
630</pre> 713</pre>
631</YueDisplay> 714</YueDisplay>
632 715
633* **Metatable Destructure** 716* **Metatable Destructure**
634Destruct metatable with metamethod key surrounded by **<>**. 717Destruct metatable with metamethod key surrounded by **<>**.
635 718
636```moonscript 719```moonscript
@@ -732,34 +815,45 @@ a ??= false
732 815
733### Implicit Object 816### Implicit Object
734 817
735You can write a list of implicit structures that starts with the symbol **\*** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. 818You can write a list of implicit structures that starts with the symbol **\*** or **-** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent.
819
736```moonscript 820```moonscript
821-- assignment with implicit object
737list = 822list =
738 * 1 823 * 1
739 * 2 824 * 2
740 * 3 825 * 3
741 826
827-- function call with implicit object
742func 828func
743 * 1 829 * 1
744 * 2 830 * 2
745 * 3 831 * 3
746 832
833-- return with implicit object
834f = ->
835 return
836 * 1
837 * 2
838 * 3
839
840-- table with implicit object
747tb = 841tb =
748 name: "abc" 842 name: "abc"
749 843
750 values: 844 values:
751 * "a" 845 - "a"
752 * "b" 846 - "b"
753 * "c" 847 - "c"
754 848
755 objects: 849 objects:
756 * name: "a" 850 - name: "a"
757 value: 1 851 value: 1
758 func: => @value + 1 852 func: => @value + 1
759 tb: 853 tb:
760 fieldA: 1 854 fieldA: 1
761 855
762 * name: "b" 856 - name: "b"
763 value: 2 857 value: 2
764 func: => @value + 2 858 func: => @value + 2
765 tb: { } 859 tb: { }
@@ -767,32 +861,42 @@ tb =
767``` 861```
768<YueDisplay> 862<YueDisplay>
769<pre> 863<pre>
864-- assignment with implicit object
770list = 865list =
771 * 1 866 * 1
772 * 2 867 * 2
773 * 3 868 * 3
774 869
870-- function call with implicit object
775func 871func
776 * 1 872 * 1
777 * 2 873 * 2
778 * 3 874 * 3
779 875
876-- return with implicit object
877f = ->
878 return
879 * 1
880 * 2
881 * 3
882
883-- table with implicit object
780tb = 884tb =
781 name: "abc" 885 name: "abc"
782 886
783 values: 887 values:
784 * "a" 888 - "a"
785 * "b" 889 - "b"
786 * "c" 890 - "c"
787 891
788 objects: 892 objects:
789 * name: "a" 893 - name: "a"
790 value: 1 894 value: 1
791 func: => @value + 1 895 func: => @value + 1
792 tb: 896 tb:
793 fieldA: 1 897 fieldA: 1
794 898
795 * name: "b" 899 - name: "b"
796 value: 2 900 value: 2
797 func: => @value + 2 901 func: => @value + 2
798 tb: { } 902 tb: { }
@@ -860,7 +964,7 @@ do
860 964
861The export statement offers a concise way to define modules. 965The export statement offers a concise way to define modules.
862 966
863* **Named Export** 967* **Named Export**
864Named export will define a local variable as well as adding a field in the exported table. 968Named export will define a local variable as well as adding a field in the exported table.
865 969
866```moonscript 970```moonscript
@@ -924,7 +1028,7 @@ export["a-b-c"] = 123
924</pre> 1028</pre>
925</YueDisplay> 1029</YueDisplay>
926 1030
927* **Unnamed Export** 1031* **Unnamed Export**
928Unnamed export will add the target item into the array part of the exported table. 1032Unnamed export will add the target item into the array part of the exported table.
929 1033
930```moonscript 1034```moonscript
@@ -954,7 +1058,7 @@ export with tmp
954</pre> 1058</pre>
955</YueDisplay> 1059</YueDisplay>
956 1060
957* **Default Export** 1061* **Default Export**
958Using the **default** keyword in export statement to replace the exported table with any thing. 1062Using the **default** keyword in export statement to replace the exported table with any thing.
959 1063
960```moonscript 1064```moonscript
@@ -1202,7 +1306,7 @@ If the destructuring statement is complicated, feel free to spread it out over a
1202</pre> 1306</pre>
1203</YueDisplay> 1307</YueDisplay>
1204 1308
1205It’s common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: 1309It's common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator:
1206 1310
1207```moonscript 1311```moonscript
1208{:concat, :insert} = table 1312{:concat, :insert} = table
@@ -1246,6 +1350,52 @@ You can use `_` as placeholder when doing a list destructuring:
1246</pre> 1350</pre>
1247</YueDisplay> 1351</YueDisplay>
1248 1352
1353### Range Destructuring
1354
1355You can use the spread operator `...` in list destructuring to capture a range of values. This is useful when you want to extract specific elements from the beginning and end of a list while collecting the rest in between.
1356
1357```moonscript
1358orders = ["first", "second", "third", "fourth", "last"]
1359[first, ...bulk, last] = orders
1360print first -- prints: first
1361print bulk -- prints: {"second", "third", "fourth"}
1362print last -- prints: last
1363```
1364<YueDisplay>
1365<pre>
1366orders = ["first", "second", "third", "fourth", "last"]
1367[first, ...bulk, last] = orders
1368print first -- prints: first
1369print bulk -- prints: {"second", "third", "fourth"}
1370print last -- prints: last
1371</pre>
1372</YueDisplay>
1373
1374The spread operator can be used in different positions to capture different ranges, and you can use `_` as a placeholder for the values you don't want to capture:
1375
1376```moonscript
1377-- Capture everything after first element
1378[first, ...rest] = orders
1379
1380-- Capture everything before last element
1381[...start, last] = orders
1382
1383-- Capture things except the middle elements
1384[first, ..._, last] = orders
1385```
1386<YueDisplay>
1387<pre>
1388-- Capture everything after first element
1389[first, ...rest] = orders
1390
1391-- Capture everything before last element
1392[...start, last] = orders
1393
1394-- Capture things except the middle elements
1395[first, ..._, last] = orders
1396</pre>
1397</YueDisplay>
1398
1249### Destructuring In Other Places 1399### Destructuring In Other Places
1250 1400
1251Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: 1401Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop:
@@ -1475,6 +1625,47 @@ catch err
1475</pre> 1625</pre>
1476</YueDisplay> 1626</YueDisplay>
1477 1627
1628### Try?
1629
1630`try?` is a simplified use for error handling syntax that omit the boolean status from the `try` statement, and it will return the result from the try block when success, return nil instead of error object otherwise.
1631
1632```moonscript
1633a, b, c = try? func!
1634
1635-- with nil coalescing operator
1636a = (try? func!) ?? "default"
1637
1638-- as function argument
1639f try? func!
1640
1641-- with catch block
1642f try?
1643 print 123
1644 func!
1645catch e
1646 print e
1647 e
1648```
1649<YueDisplay>
1650<pre>
1651a, b, c = try? func!
1652
1653-- with nil coalescing operator
1654a = (try? func!) ?? "default"
1655
1656-- as function argument
1657f try? func!
1658
1659-- with catch block
1660f try?
1661 print 123
1662 func!
1663catch e
1664 print e
1665 e
1666</pre>
1667</YueDisplay>
1668
1478## Attributes 1669## Attributes
1479 1670
1480Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. 1671Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4.
@@ -1503,6 +1694,19 @@ const {:a, :b, c, d} = tb
1503</pre> 1694</pre>
1504</YueDisplay> 1695</YueDisplay>
1505 1696
1697You can also declare a global variable to be `const`.
1698
1699```moonscript
1700global const Constant = 123
1701-- Constant = 1
1702```
1703<YueDisplay>
1704<pre>
1705global const Constant = 123
1706-- Constant = 1
1707</pre>
1708</YueDisplay>
1709
1506## Literals 1710## Literals
1507 1711
1508All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. 1712All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**.
@@ -1535,12 +1739,73 @@ You can use underscores in a number literal to increase readability.
1535```moonscript 1739```moonscript
1536integer = 1_000_000 1740integer = 1_000_000
1537hex = 0xEF_BB_BF 1741hex = 0xEF_BB_BF
1742binary = 0B10011
1538``` 1743```
1539<YueDisplay> 1744<YueDisplay>
1540 1745
1541<pre> 1746<pre>
1542integer = 1_000_000 1747integer = 1_000_000
1543hex = 0xEF_BB_BF 1748hex = 0xEF_BB_BF
1749binary = 0B10011
1750</pre>
1751</YueDisplay>
1752
1753### YAML Multiline String
1754
1755The `|` prefix introduces a YAML-style multiline string literal:
1756
1757```moonscript
1758str = |
1759 key: value
1760 list:
1761 - item1
1762 - #{expr}
1763```
1764<YueDisplay>
1765<pre>
1766str = |
1767 key: value
1768 list:
1769 - item1
1770 - #{expr}
1771</pre>
1772</YueDisplay>
1773
1774This allows writing structured multiline text conveniently. All line breaks and indentation are preserved relative to the first non-empty line, and expressions inside `#{...}` are interpolated automatically as `tostring(expr)`.
1775
1776YAML Multiline String automatically detects the common leading whitespace prefix (minimum indentation across all non-empty lines) and removes it from all lines. This makes it easy to indent your code visually without affecting the resulting string content.
1777
1778```moonscript
1779fn = ->
1780 str = |
1781 foo:
1782 bar: baz
1783 return str
1784```
1785<YueDisplay>
1786<pre>
1787fn = ->
1788 str = |
1789 foo:
1790 bar: baz
1791 return str
1792</pre>
1793</YueDisplay>
1794
1795Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures.
1796
1797All special characters like quotes (`"`) and backslashes (`\`) in the YAMLMultiline block are automatically escaped so that the generated Lua string is syntactically valid and behaves as expected.
1798
1799```moonscript
1800str = |
1801 path: "C:\Program Files\App"
1802 note: 'He said: "#{Hello}!"'
1803```
1804<YueDisplay>
1805<pre>
1806str = |
1807 path: "C:\Program Files\App"
1808 note: 'He said: "#{Hello}!"'
1544</pre> 1809</pre>
1545</YueDisplay> 1810</YueDisplay>
1546 1811
@@ -1861,6 +2126,89 @@ if func 1, 2, 3,
1861</pre> 2126</pre>
1862</YueDisplay> 2127</YueDisplay>
1863 2128
2129### Parameter Destructuring
2130
2131YueScript 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
2138f1 = (:a, :b, :c) ->
2139 print a, b, c
2140
2141f1 a: 1, b: "2", c: {}
2142
2143f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2144 print a1, b, c
2145
2146arg1 = {a: 0}
2147f2 arg1, arg2
2148```
2149<YueDisplay>
2150<pre>
2151f1 = (:a, :b, :c) ->
2152 print a, b, c
2153
2154f1 a: 1, b: "2", c: {}
2155
2156f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2157print a1, b, c
2158
2159arg1 = {a: 0}
2160f2 arg1, arg2
2161</pre>
2162</YueDisplay>
2163
2164### Prefixed Return Expression
2165
2166When 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
2169findFirstEven = (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>
2178findFirstEven = (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
2187This is equivalent to:
2188
2189```moon
2190findFirstEven = (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>
2200findFirstEven = (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
2210The 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
1866Backcalls 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. 2214Backcalls 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
1905If you wish to have further code after your backcalls, you can set them aside with a do statement. 2253If 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
1908result, msg = do 2256result, 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
1913print result, msg 2261print result, msg
1914``` 2262```
1915<YueDisplay> 2263<YueDisplay>
1916<pre> 2264<pre>
1917result, msg = do 2265result, 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
1922print result, msg 2270print result, msg
1923</pre> 2271</pre>
@@ -2096,13 +2444,11 @@ doubled = [item * 2 for i, item in ipairs items]
2096The items included in the new table can be restricted with a when clause: 2444The items included in the new table can be restricted with a when clause:
2097 2445
2098```moonscript 2446```moonscript
2099iter = ipairs items 2447slice = [item for i, item in ipairs items when i > 1 and i < 3]
2100slice = [item for i, item in iter when i > 1 and i < 3]
2101``` 2448```
2102<YueDisplay> 2449<YueDisplay>
2103<pre> 2450<pre>
2104iter = ipairs items 2451slice = [item for i, item in ipairs items when i > 1 and i < 3]
2105slice = [item for i, item in iter when i > 1 and i < 3]
2106</pre> 2452</pre>
2107</YueDisplay> 2453</YueDisplay>
2108 2454
@@ -2250,6 +2596,45 @@ slice = [item for item in *items[,,2]]
2250</pre> 2596</pre>
2251</YueDisplay> 2597</YueDisplay>
2252 2598
2599Both 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
2603slice = [item for item in *items[-4,-1]]
2604```
2605<YueDisplay>
2606<pre>
2607-- take the last 4 items
2608slice = [item for item in *items[-4,-1]]
2609</pre>
2610</YueDisplay>
2611
2612The step size can also be negative, which means that the items are taken in reverse order.
2613
2614```moonscript
2615reverse_slice = [item for item in *items[-1,1,-1]]
2616```
2617<YueDisplay>
2618<pre>
2619reverse_slice = [item for item in *items[-1,1,-1]]
2620</pre>
2621</YueDisplay>
2622
2623#### Slicing Expression
2624
2625Slicing 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
2629sub_list = items[2, 4]
2630```
2631<YueDisplay>
2632<pre>
2633-- take the 2nd and 4th items as a new list
2634sub_list = items[2, 4]
2635</pre>
2636</YueDisplay>
2637
2253## For Loop 2638## For Loop
2254 2639
2255There are two for loop forms, just like in Lua. A numeric one and a generic one: 2640There are two for loop forms, just like in Lua. A numeric one and a generic one:
@@ -2326,6 +2711,23 @@ doubled_evens = for i = 1, 20
2326</pre> 2711</pre>
2327</YueDisplay> 2712</YueDisplay>
2328 2713
2714In 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
2716For example, to find the first number greater than 10:
2717
2718```moonscript
2719first_large = for n in *numbers
2720 break n if n > 10
2721```
2722<YueDisplay>
2723<pre>
2724first_large = for n in *numbers
2725 break n if n > 10
2726</pre>
2727</YueDisplay>
2728
2729This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions.
2730
2329You can also filter values by combining the for loop expression with the continue statement. 2731You can also filter values by combining the for loop expression with the continue statement.
2330 2732
2331For 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. 2733For 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.
@@ -2347,7 +2749,7 @@ print func_b! -- prints table object
2347</pre> 2749</pre>
2348</YueDisplay> 2750</YueDisplay>
2349 2751
2350This is done to avoid the needless creation of tables for functions that dont need to return the results of the loop. 2752This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop.
2351 2753
2352## Repeat Loop 2754## Repeat Loop
2353 2755
@@ -2626,28 +3028,26 @@ reader\parse_line! until reader\eof!
2626 3028
2627## Switch 3029## Switch
2628 3030
2629The 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. 3031The 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.
2630 3032
2631```moonscript 3033```moonscript
2632name = "Dan" 3034switch name := "Dan"
2633switch name
2634 when "Robert" 3035 when "Robert"
2635 print "You are Robert" 3036 print "You are Robert"
2636 when "Dan", "Daniel" 3037 when "Dan", "Daniel"
2637 print "Your name, it's Dan" 3038 print "Your name, it's Dan"
2638 else 3039 else
2639 print "I don't know about your name" 3040 print "I don't know about you with name #{name}"
2640``` 3041```
2641<YueDisplay> 3042<YueDisplay>
2642<pre> 3043<pre>
2643name = "Dan" 3044switch name := "Dan"
2644switch name
2645 when "Robert" 3045 when "Robert"
2646 print "You are Robert" 3046 print "You are Robert"
2647 when "Dan", "Daniel" 3047 when "Dan", "Daniel"
2648 print "Your name, it's Dan" 3048 print "Your name, it's Dan"
2649 else 3049 else
2650 print "I don't know about your name" 3050 print "I don't know about you with name #{name}"
2651</pre> 3051</pre>
2652</YueDisplay> 3052</YueDisplay>
2653 3053
@@ -2678,7 +3078,7 @@ next_number = switch b
2678</pre> 3078</pre>
2679</YueDisplay> 3079</YueDisplay>
2680 3080
2681We 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. 3081We 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.
2682 3082
2683```moonscript 3083```moonscript
2684msg = switch math.random(1, 5) 3084msg = switch math.random(1, 5)
@@ -2724,7 +3124,7 @@ else
2724</pre> 3124</pre>
2725</YueDisplay> 3125</YueDisplay>
2726 3126
2727It 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. 3127It 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.
2728 3128
2729### Table Matching 3129### Table Matching
2730 3130
@@ -2784,6 +3184,123 @@ switch item
2784</pre> 3184</pre>
2785</YueDisplay> 3185</YueDisplay>
2786 3186
3187You can also match against array elements, table fields, and even nested structures with array or table literals.
3188
3189Match against array elements.
3190
3191```moonscript
3192switch 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>
3202switch 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
3212Match against table fields with destructuring.
3213
3214```moonscript
3215switch 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>
3225switch 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
3235Match against nested table structures.
3236
3237```moonscript
3238switch 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>
3248switch 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
3258Match against array of tables.
3259
3260```moonscript
3261switch 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>
3272switch 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
3283Match against a list and capture a range of elements.
3284
3285```moonscript
3286segments = ["admin", "users", "logs", "view"]
3287switch 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>
3295segments = ["admin", "users", "logs", "view"]
3296switch 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
2787## Object Oriented Programming 3304## Object Oriented Programming
2788 3305
2789In 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. 3306In 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.
@@ -2915,7 +3432,7 @@ class BackPack extends Inventory
2915 3432
2916Here we extend our Inventory class, and limit the amount of items it can carry. 3433Here we extend our Inventory class, and limit the amount of items it can carry.
2917 3434
2918In 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. 3435In 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.
2919 3436
2920Whenever 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. 3437Whenever 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.
2921 3438
@@ -3002,13 +3519,13 @@ print BackPack.size -- prints 10
3002 3519
3003The 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. 3520The 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.
3004 3521
3005The 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. 3522The 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.
3006 3523
3007A 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. 3524A 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.
3008 3525
3009The 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. 3526The 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.
3010 3527
3011It 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. 3528It 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.
3012 3529
3013The class object has a couple special properties: 3530The class object has a couple special properties:
3014 3531
@@ -3081,7 +3598,7 @@ print Counter.count -- prints 2
3081</pre> 3598</pre>
3082</YueDisplay> 3599</YueDisplay>
3083 3600
3084The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua’s colon syntax. 3601The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax.
3085 3602
3086```moonscript 3603```moonscript
3087@@hello 1,2,3,4 3604@@hello 1,2,3,4
@@ -3096,7 +3613,7 @@ The calling semantics of @@ are similar to @. Calling a @@ name will pass the cl
3096 3613
3097In 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. 3614In 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.
3098 3615
3099Here is an alternative way to create a class variable compared to whats described above: 3616Here is an alternative way to create a class variable compared to what's described above:
3100 3617
3101```moonscript 3618```moonscript
3102class Things 3619class Things
@@ -3362,19 +3879,19 @@ In this usage, with can be seen as a special form of the K combinator.
3362The expression in the with statement can also be an assignment, if you want to give a name to the expression. 3879The expression in the with statement can also be an assignment, if you want to give a name to the expression.
3363 3880
3364```moonscript 3881```moonscript
3365with str = "Hello" 3882with str := "Hello"
3366 print "original:", str 3883 print "original:", str
3367 print "upper:", \upper! 3884 print "upper:", \upper!
3368``` 3885```
3369<YueDisplay> 3886<YueDisplay>
3370<pre> 3887<pre>
3371with str = "Hello" 3888with str := "Hello"
3372 print "original:", str 3889 print "original:", str
3373 print "upper:", \upper! 3890 print "upper:", \upper!
3374</pre> 3891</pre>
3375</YueDisplay> 3892</YueDisplay>
3376 3893
3377Accessing special keys with `[]` in a `with` statement. 3894You can access special keys with `[]` in a `with` statement.
3378 3895
3379```moonscript 3896```moonscript
3380with tb 3897with tb
@@ -3397,6 +3914,18 @@ with tb
3397</pre> 3914</pre>
3398</YueDisplay> 3915</YueDisplay>
3399 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
3920with? obj
3921 print obj.name
3922```
3923<YueDisplay>
3924<pre>
3925with? obj
3926 print obj.name
3927</pre>
3928</YueDisplay>
3400 3929
3401## Do 3930## Do
3402 3931
@@ -3417,7 +3946,7 @@ print var -- nil here
3417</pre> 3946</pre>
3418</YueDisplay> 3947</YueDisplay>
3419 3948
3420YueScript’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. 3949YueScript'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.
3421 3950
3422```moonscript 3951```moonscript
3423counter = do 3952counter = do
@@ -3543,7 +4072,7 @@ print i -- will print 0
3543</pre> 4072</pre>
3544</YueDisplay> 4073</YueDisplay>
3545 4074
3546In 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. 4075In 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.
3547 4076
3548It 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. 4077It 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.
3549 4078
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md
index 1a2da96..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-- 导入语法
19import "yue" as :p, :to_lua 19import p, to_lua from "yue"
20 20
21-- 隐式对象 21-- 隐式对象
22inventory = 22inventory =
23 equipment: 23 equipment:
24 * "sword" 24 - "sword"
25 * "shield" 25 - "shield"
26 items: 26 items:
27 * name: "potion" 27 - name: "potion"
28 count: 10 28 count: 10
29 * name: "bread" 29 - name: "bread"
30 count: 3 30 count: 3
31 31
32-- 列表推导
33map = (arr, action) ->
34 [action item for item in *arr]
35
36filter = (arr, cond) ->
37 [item for item in *arr when cond item]
38
39reduce = (arr, init, action): init ->
40 init = action init, item for item in *arr
41
32-- 管道操作符 42-- 管道操作符
33[1, 2, 3] 43[1, 2, 3]
34 |> map (x) -> x * 2 44 |> map (x) -> x * 2
@@ -51,19 +61,29 @@ export 🌛 = "月之脚本"
51<YueDisplay> 61<YueDisplay>
52<pre> 62<pre>
53-- 导入语法 63-- 导入语法
54import "yue" as :p, :to_lua 64import p, to_lua from "yue"
55 65
56-- 隐式对象 66-- 隐式对象
57inventory = 67inventory =
58 equipment: 68 equipment:
59 * "sword" 69 - "sword"
60 * "shield" 70 - "shield"
61 items: 71 items:
62 * name: "potion" 72 - name: "potion"
63 count: 10 73 count: 10
64 * name: "bread" 74 - name: "bread"
65 count: 3 75 count: 3
66 76
77-- 列表推导
78map = (arr, action) ->
79 [action item for item in *arr]
80
81filter = (arr, cond) ->
82 [item for item in *arr when cond item]
83
84reduce = (arr, init, action): init ->
85 init = action init, item for item in *arr
86
67-- 管道操作符 87-- 管道操作符
68[1, 2, 3] 88[1, 2, 3]
69 |> map (x) -> x * 2 89 |> map (x) -> x * 2
@@ -122,7 +142,7 @@ export 🌛 = "月之脚本"
122 142
123* **下载预编译的二进制程序** 143* **下载预编译的二进制程序**
124 144
125&emsp;可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。 145&emsp;可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。
126 146
127&emsp;在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。 147&emsp;在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。
128 148
@@ -132,14 +152,14 @@ export 🌛 = "月之脚本"
132 152
133在Lua中使用月之脚本模块: 153在Lua中使用月之脚本模块:
134 154
135* **用法 1** 155* **用法 1**
136在Lua中引入 "你的脚本入口文件.yue"。 156在Lua中引入 "你的脚本入口文件.yue"。
137```Lua 157```Lua
138require("yue")("你的脚本入口文件") 158require("yue")("你的脚本入口文件")
139``` 159```
140当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import**进行脚本引用即可。错误消息中的代码行号也会被正确处理。 160当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import**进行脚本引用即可。错误消息中的代码行号也会被正确处理。
141 161
142* **用法 2** 162* **用法 2**
143手动引入月之脚本模块并重写错误消息来帮助调试。 163手动引入月之脚本模块并重写错误消息来帮助调试。
144```lua 164```lua
145local yue = require("yue") 165local yue = require("yue")
@@ -151,7 +171,7 @@ end, function(err)
151end) 171end)
152``` 172```
153 173
154* **用法 3** 174* **用法 3**
155在Lua中使用月之脚本编译器功能。 175在Lua中使用月之脚本编译器功能。
156```lua 176```lua
157local yue = require("yue") 177local yue = require("yue")
@@ -202,12 +222,12 @@ f!
202 不添加任何选项执行命令可以进入REPL模式, 222 不添加任何选项执行命令可以进入REPL模式,
203 在单行输入符号 '$' 并换行后,可以开始或是停止多行输入模式 223 在单行输入符号 '$' 并换行后,可以开始或是停止多行输入模式
204``` 224```
205&emsp;&emsp;使用案例: 225&emsp;&emsp;使用案例:
206&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .** 226&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .**
207&emsp;&emsp;编译并将结果保存到目标路径: **yue -t /target/path/ .** 227&emsp;&emsp;编译并将结果保存到目标路径: **yue -t /target/path/ .**
208&emsp;&emsp;编译并保留调试信息: **yue -l .** 228&emsp;&emsp;编译并保留调试信息: **yue -l .**
209&emsp;&emsp;编译并生成压缩代码: **yue -m .** 229&emsp;&emsp;编译并生成压缩代码: **yue -m .**
210&emsp;&emsp;直接执行代码: **yue -e 'print 123'** 230&emsp;&emsp;直接执行代码: **yue -e 'print 123'**
211&emsp;&emsp;执行一个月之脚本文件: **yue -e main.yue** 231&emsp;&emsp;执行一个月之脚本文件: **yue -e main.yue**
212 232
213## 宏 233## 宏
@@ -333,7 +353,7 @@ end
333 353
334### 导出宏 354### 导出宏
335 355
336宏函数可以从一个模块中导出,并在另一个模块中导入。您必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。 356宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。
337```moonscript 357```moonscript
338-- 文件: utils.yue 358-- 文件: utils.yue
339export macro map = (items, action) -> "[#{action} for _ in *#{items}]" 359export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
@@ -422,6 +442,54 @@ print "有效的枚举类型:", $BodyType Static
422</pre> 442</pre>
423</YueDisplay> 443</YueDisplay>
424 444
445### 宏参数检查
446
447可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。
448
449```moonscript
450macro printNumAndStr = (num `Num, str `String) -> |
451 print(
452 #{num}
453 #{str}
454 )
455
456$printNumAndStr 123, "hello"
457```
458<YueDisplay>
459<pre>
460macro printNumAndStr = (num `Num, str `String) -> |
461 print(
462 #{num}
463 #{str}
464 )
465
466$printNumAndStr 123, "hello"
467</pre>
468</YueDisplay>
469
470如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。
471
472```moonscript
473macro printNumAndStr = (num, str) ->
474 error "expected Num as first argument" unless $is_ast Num, num
475 error "expected String as second argument" unless $is_ast String, str
476 "print(#{num}, #{str})"
477
478$printNumAndStr 123, "hello"
479```
480<YueDisplay>
481<pre>
482macro printNumAndStr = (num, str) ->
483 error "expected Num as first argument" unless $is_ast Num, num
484 error "expected String as second argument" unless $is_ast String, str
485 "print(#{num}, #{str})"
486
487$printNumAndStr 123, "hello"
488</pre>
489</YueDisplay>
490
491更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。
492
425## 操作符 493## 操作符
426 494
427Lua的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。 495Lua的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。
@@ -439,7 +507,7 @@ tb::func! if tb != nil
439 507
440### 链式比较 508### 链式比较
441 509
442可以在月之脚本中进行比较表达式的链式书写: 510可以在月之脚本中进行比较表达式的链式书写:
443 511
444```moonscript 512```moonscript
445print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 513print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
@@ -528,7 +596,7 @@ tab[] = "Value"
528 596
529### 表扩展 597### 表扩展
530 598
531可以使用前置 `...` 操作符在Lua表中插入数组表或哈希表。 599可以使用前置 `...` 操作符在Lua表中插入数组表或哈希表。
532 600
533```moonscript 601```moonscript
534parts = 602parts =
@@ -565,11 +633,26 @@ merge = {...a, ...b}
565</pre> 633</pre>
566</YueDisplay> 634</YueDisplay>
567 635
636### 表反向索引
637
638你可以使用 **#** 操作符来反向索引表中的元素。
639
640```moonscript
641last = data.items[#]
642second_last = data.items[#-1]
643```
644<YueDisplay>
645<pre>
646last = data.items[#]
647second_last = data.items[#-1]
648</pre>
649</YueDisplay>
650
568### 元表 651### 元表
569 652
570**<>** 操作符可提供元表操作的快捷方式。 653**<>** 操作符可提供元表操作的快捷方式。
571 654
572* **元表创建** 655* **元表创建**
573使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。 656使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。
574 657
575```moonscript 658```moonscript
@@ -605,7 +688,7 @@ close _ = &lt;close&gt;: -> print "超出范围"
605</pre> 688</pre>
606</YueDisplay> 689</YueDisplay>
607 690
608* **元表访问** 691* **元表访问**
609使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。 692使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。
610 693
611```moonscript 694```moonscript
@@ -629,7 +712,7 @@ print tb.item
629</pre> 712</pre>
630</YueDisplay> 713</YueDisplay>
631 714
632* **元表解构** 715* **元表解构**
633使用被 **<>** 包围的元方法键解构元表。 716使用被 **<>** 包围的元方法键解构元表。
634 717
635```moonscript 718```moonscript
@@ -680,7 +763,7 @@ with? io.open "test.txt", "w"
680 763
681### 管道 764### 管道
682 765
683与其使用一系列嵌套的函数调用,还可以考虑使用运算符 **|>** 来传递值。 766与其使用一系列嵌套的函数调用,还可以考虑使用运算符 **|>** 来传递值。
684 767
685```moonscript 768```moonscript
686"你好" |> print 769"你好" |> print
@@ -731,67 +814,87 @@ a ??= false
731 814
732### 隐式对象 815### 隐式对象
733 816
734您可以在表格块内使用符号 **\*** 开始编写一系列隐式结构。如果您正在创建隐式对象,对象的字段必须具有相同的缩进。 817你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。
818
735```moonscript 819```moonscript
820-- 赋值时使用隐式对象
736list = 821list =
737 * 1 822 * 1
738 * 2 823 * 2
739 * 3 824 * 3
740 825
826-- 函数调用时使用隐式对象
741func 827func
742 * 1 828 * 1
743 * 2 829 * 2
744 * 3 830 * 3
745 831
832-- 返回时使用隐式对象
833f = ->
834 return
835 * 1
836 * 2
837 * 3
838
839-- 表格时使用隐式对象
746tb = 840tb =
747 name: "abc" 841 name: "abc"
748 842
749 values: 843 values:
750 * "a" 844 - "a"
751 * "b" 845 - "b"
752 * "c" 846 - "c"
753 847
754 objects: 848 objects:
755 * name: "a" 849 - name: "a"
756 value: 1 850 value: 1
757 func: => @value + 1 851 func: => @value + 1
758 tb: 852 tb:
759 fieldA: 1 853 fieldA: 1
760 854
761 * name: "b" 855 - name: "b"
762 value: 2 856 value: 2
763 func: => @value + 2 857 func: => @value + 2
764 tb: { } 858 tb: { }
765
766``` 859```
767<YueDisplay> 860<YueDisplay>
768<pre> 861<pre>
862-- 赋值时使用隐式对象
769list = 863list =
770 * 1 864 * 1
771 * 2 865 * 2
772 * 3 866 * 3
773 867
868-- 函数调用时使用隐式对象
774func 869func
775 * 1 870 * 1
776 * 2 871 * 2
777 * 3 872 * 3
778 873
874-- 返回时使用隐式对象
875f = ->
876 return
877 * 1
878 * 2
879 * 3
880
881-- 表格时使用隐式对象
779tb = 882tb =
780 name: "abc" 883 name: "abc"
781 884
782 values: 885 values:
783 * "a" 886 - "a"
784 * "b" 887 - "b"
785 * "c" 888 - "c"
786 889
787 objects: 890 objects:
788 * name: "a" 891 - name: "a"
789 value: 1 892 value: 1
790 func: => @value + 1 893 func: => @value + 1
791 tb: 894 tb:
792 fieldA: 1 895 fieldA: 1
793 896
794 * name: "b" 897 - name: "b"
795 value: 2 898 value: 2
796 func: => @value + 2 899 func: => @value + 2
797 tb: { } 900 tb: { }
@@ -859,7 +962,7 @@ do
859 962
860导出语句提供了一种简洁的方式来定义当前的模块。 963导出语句提供了一种简洁的方式来定义当前的模块。
861 964
862* **命名导出** 965* **命名导出**
863带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。 966带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。
864 967
865```moonscript 968```moonscript
@@ -923,7 +1026,7 @@ export["a-b-c"] = 123
923</pre> 1026</pre>
924</YueDisplay> 1027</YueDisplay>
925 1028
926* **未命名导出** 1029* **未命名导出**
927未命名导出会将要导出的目标项目添加到导出表的数组部分。 1030未命名导出会将要导出的目标项目添加到导出表的数组部分。
928 1031
929```moonscript 1032```moonscript
@@ -953,7 +1056,7 @@ export with tmp
953</pre> 1056</pre>
954</YueDisplay> 1057</YueDisplay>
955 1058
956* **默认导出** 1059* **默认导出**
957在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。 1060在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。
958 1061
959```moonscript 1062```moonscript
@@ -1223,7 +1326,7 @@ print first, second, color
1223</pre> 1326</pre>
1224</YueDisplay> 1327</YueDisplay>
1225 1328
1226在进行解构时,可以指定默认值,如: 1329在进行解构时,可以指定默认值,如:
1227 1330
1228```moonscript 1331```moonscript
1229{:name = "nameless", :job = "jobless"} = person 1332{:name = "nameless", :job = "jobless"} = person
@@ -1234,7 +1337,7 @@ print first, second, color
1234</pre> 1337</pre>
1235</YueDisplay> 1338</YueDisplay>
1236 1339
1237在进行列表解构时,可以使用`_`作为占位符: 1340在进行列表解构时,可以使用`_`作为占位符:
1238 1341
1239```moonscript 1342```moonscript
1240[_, two, _, four] = items 1343[_, two, _, four] = items
@@ -1245,9 +1348,55 @@ print first, second, color
1245</pre> 1348</pre>
1246</YueDisplay> 1349</YueDisplay>
1247 1350
1248### 在其它地方的解构 1351### 范围解构
1352
1353你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。
1354
1355```moonscript
1356orders = ["first", "second", "third", "fourth", "last"]
1357[first, ...bulk, last] = orders
1358print first -- 打印: first
1359print bulk -- 打印: {"second", "third", "fourth"}
1360print last -- 打印: last
1361```
1362<YueDisplay>
1363<pre>
1364orders = ["first", "second", "third", "fourth", "last"]
1365[first, ...bulk, last] = orders
1366print first -- 打印: first
1367print bulk -- 打印: {"second", "third", "fourth"}
1368print last -- 打印: last
1369</pre>
1370</YueDisplay>
1371
1372展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获:
1373
1374```moonscript
1375-- 捕获第一个元素之后的所有元素
1376[first, ...rest] = orders
1377
1378-- 捕获最后一个元素之前的所有元素
1379[...start, last] = orders
1380
1381-- 跳过中间的元素,只捕获第一个和最后一个元素
1382[first, ..._, last] = orders
1383```
1384<YueDisplay>
1385<pre>
1386-- 捕获第一个元素之后的所有元素
1387[first, ...rest] = orders
1388
1389-- 捕获最后一个元素之前的所有元素
1390[...start, last] = orders
1391
1392-- 跳过中间的元素,只捕获第一个和最后一个元素
1393[first, ..._, last] = orders
1394</pre>
1395</YueDisplay>
1396
1397### 在其它地方的解构赋值
1249 1398
1250解构也可以出现在其它隐式进行赋值的地方。一个例子是用在for循环: 1399解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在for循环
1251 1400
1252```moonscript 1401```moonscript
1253tuples = [ 1402tuples = [
@@ -1322,7 +1471,7 @@ print "好的"
1322 1471
1323### While 赋值 1472### While 赋值
1324 1473
1325可以在 while 循环中同样使用赋值来获取循环条件的值。 1474可以在 while 循环中同样使用赋值来获取循环条件的值。
1326```moonscript 1475```moonscript
1327while byte := stream\read_one! 1476while byte := stream\read_one!
1328 -- 对 byte 做一些操作 1477 -- 对 byte 做一些操作
@@ -1338,7 +1487,7 @@ while byte := stream\read_one!
1338 1487
1339## 可变参数赋值 1488## 可变参数赋值
1340 1489
1341可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用Lua的方式访问其内容。 1490可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用Lua的方式访问其内容。
1342```moonscript 1491```moonscript
1343list = [1, 2, 3, 4, 5] 1492list = [1, 2, 3, 4, 5]
1344fn = (ok) -> ok, table.unpack list 1493fn = (ok) -> ok, table.unpack list
@@ -1360,7 +1509,7 @@ print ok, count, first
1360 1509
1361## 空白 1510## 空白
1362 1511
1363月之脚本是一个对空白敏感的语言。您必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。 1512月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。
1364 1513
1365### 多行链式调用 1514### 多行链式调用
1366 1515
@@ -1474,6 +1623,47 @@ catch err
1474</pre> 1623</pre>
1475</YueDisplay> 1624</YueDisplay>
1476 1625
1626### 错误处理简化
1627
1628`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。
1629
1630```moonscript
1631a, b, c = try? func!
1632
1633-- 与空值合并运算符一起使用
1634a = (try? func!) ?? "default"
1635
1636-- 作为函数参数
1637f try? func!
1638
1639-- 带 catch 块的 try!
1640f try?
1641 print 123
1642 func!
1643catch e
1644 print e
1645 e
1646```
1647<YueDisplay>
1648<pre>
1649a, b, c = try? func!
1650
1651-- 与空值合并运算符一起使用
1652a = (try? func!) ?? "default"
1653
1654-- 作为函数参数
1655f try? func!
1656
1657-- 带 catch 块的 try!
1658f try?
1659 print 123
1660 func!
1661catch e
1662 print e
1663 e
1664</pre>
1665</YueDisplay>
1666
1477## 属性 1667## 属性
1478 1668
1479月之脚本现在提供了Lua 5.4新增的叫做属性的语法支持。在月之脚本编译到的Lua目标版本低于5.4时,你仍然可以同时使用`const`和`close`的属性声明语法,并获得常量检查和作用域回调的功能。 1669月之脚本现在提供了Lua 5.4新增的叫做属性的语法支持。在月之脚本编译到的Lua目标版本低于5.4时,你仍然可以同时使用`const`和`close`的属性声明语法,并获得常量检查和作用域回调的功能。
@@ -1502,6 +1692,19 @@ const {:a, :b, c, d} = tb
1502</pre> 1692</pre>
1503</YueDisplay> 1693</YueDisplay>
1504 1694
1695你也可以声明全局变量为常量。
1696
1697```moonscript
1698global const Constant = 123
1699-- Constant = 1
1700```
1701<YueDisplay>
1702<pre>
1703global const Constant = 123
1704-- Constant = 1
1705</pre>
1706</YueDisplay>
1707
1505## 字面量 1708## 字面量
1506 1709
1507Lua中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和**nil**。 1710Lua中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和**nil**。
@@ -1529,17 +1732,78 @@ print "我有#{math.random! * 100}%的把握。"
1529 1732
1530### 数字字面量 1733### 数字字面量
1531 1734
1532可以在数字字面量中使用下划线来增加可读性。 1735可以在数字字面量中使用下划线来增加可读性。
1533 1736
1534```moonscript 1737```moonscript
1535integer = 1_000_000 1738integer = 1_000_000
1536hex = 0xEF_BB_BF 1739hex = 0xEF_BB_BF
1740binary = 0B10011
1537``` 1741```
1538<YueDisplay> 1742<YueDisplay>
1539 1743
1540<pre> 1744<pre>
1541integer = 1_000_000 1745integer = 1_000_000
1542hex = 0xEF_BB_BF 1746hex = 0xEF_BB_BF
1747binary = 0B10011
1748</pre>
1749</YueDisplay>
1750
1751### YAML 风格字符串
1752
1753使用 `|` 前缀标记一个多行 YAML 风格字符串:
1754
1755```moonscript
1756str = |
1757 key: value
1758 list:
1759 - item1
1760 - #{expr}
1761```
1762<YueDisplay>
1763<pre>
1764str = |
1765 key: value
1766 list:
1767 - item1
1768 - #{expr}
1769</pre>
1770</YueDisplay>
1771
1772其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。
1773
1774YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。
1775
1776```moonscript
1777fn = ->
1778 str = |
1779 foo:
1780 bar: baz
1781 return str
1782```
1783<YueDisplay>
1784<pre>
1785fn = ->
1786 str = |
1787 foo:
1788 bar: baz
1789 return str
1790</pre>
1791</YueDisplay>
1792
1793输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。
1794
1795支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义:
1796
1797```moonscript
1798str = |
1799 path: "C:\Program Files\App"
1800 note: 'He said: "#{Hello}!"'
1801```
1802<YueDisplay>
1803<pre>
1804str = |
1805 path: "C:\Program Files\App"
1806 note: 'He said: "#{Hello}!"'
1543</pre> 1807</pre>
1544</YueDisplay> 1808</YueDisplay>
1545 1809
@@ -1644,7 +1908,7 @@ print "数字的和是", sum 10, 20
1644</pre> 1908</pre>
1645</YueDisplay> 1909</YueDisplay>
1646 1910
1647如果需要做显式返回,可以使用return关键字: 1911如果需要做显式返回,可以使用return关键字:
1648 1912
1649```moonscript 1913```moonscript
1650sum = (x, y) -> return x + y 1914sum = (x, y) -> return x + y
@@ -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
2098f1 = (:a, :b, :c) ->
2099 print a, b, c
2100
2101f1 a: 1, b: "2", c: {}
2102
2103f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2104 print a1, b, c
2105
2106arg1 = {a: 0}
2107f2 arg1, arg2
2108```
2109<YueDisplay>
2110<pre>
2111f1 = (:a, :b, :c) ->
2112 print a, b, c
2113
2114f1 a: 1, b: "2", c: {}
2115
2116f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2117 print a1, b, c
2118
2119arg1 = {a: 0}
2120f2 arg1, arg2
2121</pre>
2122</YueDisplay>
2123
2124### 前置返回表达式
2125
2126在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下:
2127
2128```moon
2129findFirstEven = (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>
2138findFirstEven = (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
2150findFirstEven = (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>
2160findFirstEven = (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
1869result, msg = do 2216result, 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
1874print result, msg 2221print result, msg
1875``` 2222```
1876<YueDisplay> 2223<YueDisplay>
1877<pre> 2224<pre>
1878result, msg = do 2225result, 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
1883print result, msg 2230print 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
@@ -2057,13 +2404,11 @@ doubled = [item * 2 for i, item in ipairs items]
2057可以使用when子句筛选新表中包含的项目: 2404可以使用when子句筛选新表中包含的项目:
2058 2405
2059```moonscript 2406```moonscript
2060iter = ipairs items 2407slice = [item for i, item in ipairs items when i > 1 and i < 3]
2061slice = [item for i, item in iter when i > 1 and i < 3]
2062``` 2408```
2063<YueDisplay> 2409<YueDisplay>
2064<pre> 2410<pre>
2065iter = ipairs items 2411slice = [item for i, item in ipairs items when i > 1 and i < 3]
2066slice = [item for i, item in iter when i > 1 and i < 3]
2067</pre> 2412</pre>
2068</YueDisplay> 2413</YueDisplay>
2069 2414
@@ -2212,6 +2557,45 @@ slice = [item for item in *items[,,2]]
2212</pre> 2557</pre>
2213</YueDisplay> 2558</YueDisplay>
2214 2559
2560最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。
2561
2562```moonscript
2563-- 取最后4个元素
2564slice = [item for item in *items[-4,-1]]
2565```
2566<YueDisplay>
2567<pre>
2568-- 取最后4个元素
2569slice = [item for item in *items[-4,-1]]
2570</pre>
2571</YueDisplay>
2572
2573切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。
2574
2575```moonscript
2576reverse_slice = [item for item in *items[-1,1,-1]]
2577```
2578<YueDisplay>
2579<pre>
2580reverse_slice = [item for item in *items[-1,1,-1]]
2581</pre>
2582</YueDisplay>
2583
2584#### 切片表达式
2585
2586切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。
2587
2588```moonscript
2589-- 取第2和第4个元素作为新的列表
2590sub_list = items[2, 4]
2591```
2592<YueDisplay>
2593<pre>
2594-- 取第2和第4个元素作为新的列表
2595sub_list = items[2, 4]
2596</pre>
2597</YueDisplay>
2598
2215## for 循环 2599## for 循环
2216 2600
2217Lua中有两种for循环形式,数字型和通用型: 2601Lua中有两种for循环形式,数字型和通用型:
@@ -2288,9 +2672,24 @@ doubled_evens = for i = 1, 20
2288</pre> 2672</pre>
2289</YueDisplay> 2673</YueDisplay>
2290 2674
2291您还可以结合for循环表达式与continue语句来过滤值。 2675此外,for循环还支持带返回值的break语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。
2676
2677例如,查找第一个大于10的数字:
2678
2679```moonscript
2680first_large = for n in *numbers
2681 break n if n > 10
2682```
2683<YueDisplay>
2684<pre>
2685first_large = for n in *numbers
2686 break n if n > 10
2687</pre>
2688</YueDisplay>
2689
2690你还可以结合for循环表达式与continue语句来过滤值。
2292 2691
2293注意出现在函数体末尾的for循环,不会被当作是一个表达式,并将循环结果累积到一个列表中作为返回值(相反,函数将返回nil)。如果要函数末尾的循环转换为列表表达式,可以使用返回语句加for循环表达式。 2692注意出现在函数体末尾的for循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加for循环表达式。
2294 2693
2295```moonscript 2694```moonscript
2296func_a = -> for i = 1, 10 do print i 2695func_a = -> for i = 1, 10 do print i
@@ -2515,7 +2914,7 @@ print "你真幸运!" unless math.random! > 0.1
2515 2914
2516### 范围表达式 2915### 范围表达式
2517 2916
2518可以使用范围表达式来编写进行范围检查的代码。 2917可以使用范围表达式来编写进行范围检查的代码。
2519 2918
2520```moonscript 2919```moonscript
2521a = 5 2920a = 5
@@ -2588,28 +2987,26 @@ reader\parse_line! until reader\eof!
2588 2987
2589## switch 语句 2988## switch 语句
2590 2989
2591switch语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和if语句一样,switch语句在最后可以接一个else代码块来处理没有匹配的情况。在生成的Lua代码中,进行比较是使用==操作符完成的。 2990switch语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和if语句一样,switch语句在最后可以接一个else代码块来处理没有匹配的情况。在生成的Lua代码中,进行比较是使用==操作符完成的。switch语句中也可以使用赋值表达式来储存临时变量值。
2592 2991
2593```moonscript 2992```moonscript
2594name = "Dan" 2993switch name := "Dan"
2595switch name
2596 when "Robert" 2994 when "Robert"
2597 print "你是Robert" 2995 print "你是Robert"
2598 when "Dan", "Daniel" 2996 when "Dan", "Daniel"
2599 print "你的名字是Dan" 2997 print "你的名字是Dan"
2600 else 2998 else
2601 print "我不知道你的名字" 2999 print "我不认识,你的名字是#{name}"
2602``` 3000```
2603<YueDisplay> 3001<YueDisplay>
2604<pre> 3002<pre>
2605name = "Dan" 3003switch name := "Dan"
2606switch name
2607 when "Robert" 3004 when "Robert"
2608 print "你是Robert" 3005 print "你是Robert"
2609 when "Dan", "Daniel" 3006 when "Dan", "Daniel"
2610 print "你的名字是Dan" 3007 print "你的名字是Dan"
2611 else 3008 else
2612 print "我不知道你的名字" 3009 print "我不认识,你的名字是#{name}"
2613</pre> 3010</pre>
2614</YueDisplay> 3011</YueDisplay>
2615 3012
@@ -2686,7 +3083,7 @@ else
2686</pre> 3083</pre>
2687</YueDisplay> 3084</YueDisplay>
2688 3085
2689值得注意的是,在生成Lua代码时,我们要做检查的目标变量会放在==表达式的右侧。当您希望给when子句的比较对象定义一个\_\_eq元方法来重载判断逻辑时,可能会有用。 3086值得注意的是,在生成Lua代码时,我们要做检查的目标变量会放在==表达式的右侧。当你希望给when子句的比较对象定义一个\_\_eq元方法来重载判断逻辑时,可能会有用。
2690 3087
2691### 表格匹配 3088### 表格匹配
2692 3089
@@ -2746,9 +3143,126 @@ switch item
2746</pre> 3143</pre>
2747</YueDisplay> 3144</YueDisplay>
2748 3145
3146你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。
3147
3148匹配数组元素。
3149
3150```moonscript
3151switch 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>
3161switch 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
3174switch 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>
3184switch 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
3197switch 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>
3207switch 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
3220switch 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>
3231switch 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
3245segments = ["admin", "users", "logs", "view"]
3246switch 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>
3254segments = ["admin", "users", "logs", "view"]
3255switch 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
2749## 面向对象编程 3263## 面向对象编程
2750 3264
2751在以下的示例中,月之脚本生成的Lua代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果您想知道关于面向对象功能的实现细节,再查看Lua代码。 3265在以下的示例中,月之脚本生成的Lua代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果你想知道关于面向对象功能的实现细节,再查看Lua代码。
2752 3266
2753一个简单的类: 3267一个简单的类:
2754 3268
@@ -3216,7 +3730,7 @@ x = class
3216 3730
3217### 类混合 3731### 类混合
3218 3732
3219您可以通过使用 `using` 关键字来实现类混合。这意味着您可以从一个普通 Lua 表格或已定义的类对象中,复制函数到您创建的新类中。当您使用普通 Lua 表格进行类混合时,您有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当您从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。 3733你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。
3220 3734
3221```moonscript 3735```moonscript
3222MyIndex = __index: var: 1 3736MyIndex = __index: var: 1
@@ -3318,22 +3832,22 @@ me = create_person "Leaf", [dad, mother, sister]
3318 3832
3319在此用法中,with可以被视为K组合子(k-combinator)的一种特殊形式。 3833在此用法中,with可以被视为K组合子(k-combinator)的一种特殊形式。
3320 3834
3321如果给表达式另外起一个名称的话,with语句中的表达式也可以是一个赋值语句。 3835如果想给表达式另外起一个名称的话,with语句中的表达式也可以是一个赋值语句。
3322 3836
3323```moonscript 3837```moonscript
3324with str = "你好" 3838with str := "你好"
3325 print "原始:", str 3839 print "原始:", str
3326 print "大写:", \upper! 3840 print "大写:", \upper!
3327``` 3841```
3328<YueDisplay> 3842<YueDisplay>
3329<pre> 3843<pre>
3330with str = "你好" 3844with str := "你好"
3331 print "原始:", str 3845 print "原始:", str
3332 print "大写:", \upper! 3846 print "大写:", \upper!
3333</pre> 3847</pre>
3334</YueDisplay> 3848</YueDisplay>
3335 3849
3336在with语句中用`[]`访问特殊键。 3850 `with` 语句中使用 `[]` 访问特殊键。
3337 3851
3338```moonscript 3852```moonscript
3339with tb 3853with tb
@@ -3356,6 +3870,19 @@ with tb
3356</pre> 3870</pre>
3357</YueDisplay> 3871</YueDisplay>
3358 3872
3873`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。
3874
3875```moonscript
3876with? obj
3877 print obj.name
3878```
3879<YueDisplay>
3880<pre>
3881with? obj
3882 print obj.name
3883</pre>
3884</YueDisplay>
3885
3359## do 语句 3886## do 语句
3360 3887
3361当用作语句时,do语句的作用就像在Lua中差不多。 3888当用作语句时,do语句的作用就像在Lua中差不多。
@@ -3375,7 +3902,7 @@ print var -- 这里是nil
3375</pre> 3902</pre>
3376</YueDisplay> 3903</YueDisplay>
3377 3904
3378月之脚本的 **do** 也可以用作表达式。允许您将多行代码的处理合并为一个表达式,并将do语句代码块的最后一个语句作为表达式返回的结果。 3905月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将do语句代码块的最后一个语句作为表达式返回的结果。
3379 3906
3380```moonscript 3907```moonscript
3381counter = do 3908counter = do
@@ -4334,8 +4861,8 @@ simplified: boolean
4334 4861
4335版权 (c) 2017-2025 李瑾 \<dragon-fly@qq.com\> 4862版权 (c) 2017-2025 李瑾 \<dragon-fly@qq.com\>
4336 4863
4337特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下: 4864特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下:
4338上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。 4865上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
4339本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。 4866本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
4340 4867
4341<CompilerModal /> 4868<CompilerModal />