aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/docs/.vitepress/config.mts140
-rwxr-xr-xdoc/docs/.vitepress/theme/components/YueCompiler.vue4
-rw-r--r--doc/docs/.vitepress/theme/custom.css1
-rw-r--r--doc/docs/.vitepress/theme/index.ts5
-rw-r--r--doc/docs/doc/assignment.md138
-rw-r--r--doc/docs/doc/attributes.md46
-rw-r--r--doc/docs/doc/backcalls.md69
-rw-r--r--doc/docs/doc/comment.md30
-rw-r--r--doc/docs/doc/comprehensions.md271
-rw-r--r--doc/docs/doc/conditionals.md149
-rw-r--r--doc/docs/doc/continue.md41
-rw-r--r--doc/docs/doc/destructuring-assignment.md240
-rw-r--r--doc/docs/doc/do.md66
-rw-r--r--doc/docs/doc/for-loop.md127
-rw-r--r--doc/docs/doc/function-literals.md494
-rw-r--r--doc/docs/doc/function-stubs.md48
-rw-r--r--doc/docs/doc/if-assignment.md72
-rwxr-xr-xdoc/docs/doc/index.md5519
-rw-r--r--doc/docs/doc/installation.md43
-rw-r--r--doc/docs/doc/introduction.md105
-rw-r--r--doc/docs/doc/licence-mit.md23
-rw-r--r--doc/docs/doc/line-decorators.md44
-rw-r--r--doc/docs/doc/literals.md110
-rw-r--r--doc/docs/doc/macro.md274
-rw-r--r--doc/docs/doc/module.md245
-rw-r--r--doc/docs/doc/object-oriented-programming.md555
-rw-r--r--doc/docs/doc/operator.md460
-rw-r--r--doc/docs/doc/switch.md296
-rw-r--r--doc/docs/doc/table-literals.md168
-rw-r--r--doc/docs/doc/the-using-clause-controlling-destructive-assignment.md98
-rw-r--r--doc/docs/doc/the-yuescript-library.md821
-rw-r--r--doc/docs/doc/try.md105
-rw-r--r--doc/docs/doc/usage.md111
-rw-r--r--doc/docs/doc/varargs-assignment.md24
-rw-r--r--doc/docs/doc/while-loop.md69
-rw-r--r--doc/docs/doc/whitespace.md43
-rw-r--r--doc/docs/doc/with-statement.md126
-rw-r--r--doc/docs/index.md3
-rw-r--r--doc/docs/zh/doc/assignment.md142
-rw-r--r--doc/docs/zh/doc/attributes.md46
-rw-r--r--doc/docs/zh/doc/backcalls.md69
-rw-r--r--doc/docs/zh/doc/comment.md30
-rw-r--r--doc/docs/zh/doc/comprehensions.md272
-rw-r--r--doc/docs/zh/doc/conditionals.md150
-rw-r--r--doc/docs/zh/doc/continue.md41
-rw-r--r--doc/docs/zh/doc/destructuring-assignment.md241
-rw-r--r--doc/docs/zh/doc/do.md66
-rw-r--r--doc/docs/zh/doc/for-loop.md125
-rw-r--r--doc/docs/zh/doc/function-literals.md494
-rw-r--r--doc/docs/zh/doc/function-stubs.md48
-rw-r--r--doc/docs/zh/doc/if-assignment.md73
-rwxr-xr-xdoc/docs/zh/doc/index.md5452
-rw-r--r--doc/docs/zh/doc/installation.md43
-rw-r--r--doc/docs/zh/doc/introduction.md103
-rw-r--r--doc/docs/zh/doc/licence-mit.md9
-rw-r--r--doc/docs/zh/doc/line-decorators.md44
-rw-r--r--doc/docs/zh/doc/literals.md111
-rw-r--r--doc/docs/zh/doc/macro.md276
-rw-r--r--doc/docs/zh/doc/module.md245
-rw-r--r--doc/docs/zh/doc/object-oriented-programming.md550
-rw-r--r--doc/docs/zh/doc/operator.md461
-rw-r--r--doc/docs/zh/doc/switch.md296
-rw-r--r--doc/docs/zh/doc/table-literals.md168
-rw-r--r--doc/docs/zh/doc/the-using-clause-controlling-destructive-assignment.md98
-rw-r--r--doc/docs/zh/doc/the-yuescript-library.md821
-rw-r--r--doc/docs/zh/doc/try.md105
-rw-r--r--doc/docs/zh/doc/usage.md110
-rw-r--r--doc/docs/zh/doc/varargs-assignment.md24
-rw-r--r--doc/docs/zh/doc/while-loop.md69
-rw-r--r--doc/docs/zh/doc/whitespace.md43
-rw-r--r--doc/docs/zh/doc/with-statement.md126
-rw-r--r--doc/docs/zh/index.md1
-rw-r--r--spec/inputs/compile_doc.yue101
-rw-r--r--spec/outputs/codes_from_doc.lua3916
-rw-r--r--spec/outputs/codes_from_doc_zh.lua3916
-rw-r--r--spec/outputs/compile_doc.lua135
76 files changed, 15295 insertions, 14908 deletions
diff --git a/doc/docs/.vitepress/config.mts b/doc/docs/.vitepress/config.mts
index da3876d..4c20685 100644
--- a/doc/docs/.vitepress/config.mts
+++ b/doc/docs/.vitepress/config.mts
@@ -15,6 +15,140 @@ const moonscriptLanguage = {
15 aliases: ['yue', 'yuescript', 'moon'], 15 aliases: ['yue', 'yuescript', 'moon'],
16} 16}
17 17
18// Generate sidebar configuration function
19function createSidebar(basePath: string, zh: boolean) {
20 return [
21 {
22 text: zh ? '介绍' : 'Introduction',
23 link: `${basePath}/introduction`,
24 },
25 {
26 text: zh ? '安装' : 'Installation',
27 link: `${basePath}/installation`,
28 },
29 {
30 text: zh ? '使用方法' : 'Usage',
31 link: `${basePath}/usage`,
32 },
33 {
34 text: zh ? '宏' : 'Macro',
35 link: `${basePath}/macro`,
36 },
37 {
38 text: zh ? '操作符' : 'Operator',
39 link: `${basePath}/operator`,
40 },
41 {
42 text: zh ? '模块' : 'Module',
43 link: `${basePath}/module`,
44 },
45 {
46 text: zh ? '赋值' : 'Assignment',
47 link: `${basePath}/assignment`,
48 },
49 {
50 text: zh ? '解构赋值' : 'Destructuring Assignment',
51 link: `${basePath}/destructuring-assignment`,
52 },
53 {
54 text: zh ? 'If 赋值' : 'If Assignment',
55 link: `${basePath}/if-assignment`,
56 },
57 {
58 text: zh ? '可变参数赋值' : 'Varargs Assignment',
59 link: `${basePath}/varargs-assignment`,
60 },
61 {
62 text: zh ? '空白' : 'Whitespace',
63 link: `${basePath}/whitespace`,
64 },
65 {
66 text: zh ? '注释' : 'Comment',
67 link: `${basePath}/comment`,
68 },
69 {
70 text: zh ? '错误处理' : 'Try',
71 link: `${basePath}/try`,
72 },
73 {
74 text: zh ? '属性' : 'Attributes',
75 link: `${basePath}/attributes`,
76 },
77 {
78 text: zh ? '字面量' : 'Literals',
79 link: `${basePath}/literals`,
80 },
81 {
82 text: zh ? '函数字面量' : 'Function Literals',
83 link: `${basePath}/function-literals`,
84 },
85 {
86 text: zh ? '反向回调' : 'Backcalls',
87 link: `${basePath}/backcalls`,
88 },
89 {
90 text: zh ? '表格字面量' : 'Table Literals',
91 link: `${basePath}/table-literals`,
92 },
93 {
94 text: zh ? '推导式' : 'Comprehensions',
95 link: `${basePath}/comprehensions`,
96 },
97 {
98 text: zh ? 'for 循环' : 'For Loop',
99 link: `${basePath}/for-loop`,
100 },
101 {
102 text: zh ? 'while 循环' : 'While Loop',
103 link: `${basePath}/while-loop`,
104 },
105 {
106 text: zh ? 'continue 语句' : 'Continue Statement',
107 link: `${basePath}/continue`,
108 },
109 {
110 text: zh ? '条件语句' : 'Conditionals',
111 link: `${basePath}/conditionals`,
112 },
113 {
114 text: zh ? '代码行修饰符' : 'Line Decorators',
115 link: `${basePath}/line-decorators`,
116 },
117 {
118 text: zh ? 'switch 语句' : 'Switch',
119 link: `${basePath}/switch`,
120 },
121 {
122 text: zh ? '面向对象编程' : 'Object Oriented Programming',
123 link: `${basePath}/object-oriented-programming`,
124 },
125 {
126 text: zh ? 'with 语句' : 'With Statement',
127 link: `${basePath}/with-statement`,
128 },
129 {
130 text: zh ? 'do 语句' : 'Do',
131 link: `${basePath}/do`,
132 },
133 {
134 text: zh ? '函数存根' : 'Function Stubs',
135 link: `${basePath}/function-stubs`,
136 },
137 {
138 text: zh ? '使用 using 语句:防止破坏性赋值' : 'The Using Clause; Controlling Destructive Assignment',
139 link: `${basePath}/the-using-clause-controlling-destructive-assignment`,
140 },
141 {
142 text: zh ? '月之脚本语言库' : 'The YueScript Library',
143 link: `${basePath}/the-yuescript-library`,
144 },
145 {
146 text: zh ? 'MIT 许可证' : 'Licence: MIT',
147 link: `${basePath}/licence-mit`,
148 },
149 ]
150}
151
18export default defineConfig({ 152export default defineConfig({
19 title: 'YueScript', 153 title: 'YueScript',
20 description: 'A language that compiles to Lua', 154 description: 'A language that compiles to Lua',
@@ -84,7 +218,8 @@ export default defineConfig({
84 { text: 'Document', link: '/doc/' }, 218 { text: 'Document', link: '/doc/' },
85 { text: 'Try yue!', link: '/try/' }, 219 { text: 'Try yue!', link: '/try/' },
86 { text: 'Github', link: 'https://github.com/IppClub/Yuescript' } 220 { text: 'Github', link: 'https://github.com/IppClub/Yuescript' }
87 ] 221 ],
222 sidebar: createSidebar('/doc', false),
88 } 223 }
89 }, 224 },
90 zh: { 225 zh: {
@@ -96,7 +231,8 @@ export default defineConfig({
96 { text: '文档', link: '/zh/doc/' }, 231 { text: '文档', link: '/zh/doc/' },
97 { text: '试一试!', link: '/zh/try/' }, 232 { text: '试一试!', link: '/zh/try/' },
98 { text: 'Github', link: 'https://github.com/IppClub/Yuescript' } 233 { text: 'Github', link: 'https://github.com/IppClub/Yuescript' }
99 ] 234 ],
235 sidebar: createSidebar('/zh/doc', true),
100 } 236 }
101 } 237 }
102 } 238 }
diff --git a/doc/docs/.vitepress/theme/components/YueCompiler.vue b/doc/docs/.vitepress/theme/components/YueCompiler.vue
index dcea692..13a5524 100755
--- a/doc/docs/.vitepress/theme/components/YueCompiler.vue
+++ b/doc/docs/.vitepress/theme/components/YueCompiler.vue
@@ -46,7 +46,7 @@ const lightPlusTheme = EditorView.theme(
46 height: '100%', 46 height: '100%',
47 backgroundColor: '#FFFFFF', 47 backgroundColor: '#FFFFFF',
48 color: '#000000', 48 color: '#000000',
49 fontSize: '0.8em' 49 fontSize: '14px'
50 }, 50 },
51 '&.cm-focused': { 51 '&.cm-focused': {
52 outline: 'none' 52 outline: 'none'
@@ -90,7 +90,7 @@ const darkPlusTheme = EditorView.theme(
90 height: '100%', 90 height: '100%',
91 backgroundColor: '#1E1E1E', 91 backgroundColor: '#1E1E1E',
92 color: '#D4D4D4', 92 color: '#D4D4D4',
93 fontSize: '0.8em' 93 fontSize: '14px'
94 }, 94 },
95 '&.cm-focused': { 95 '&.cm-focused': {
96 outline: 'none' 96 outline: 'none'
diff --git a/doc/docs/.vitepress/theme/custom.css b/doc/docs/.vitepress/theme/custom.css
index 7b4e593..bd89528 100644
--- a/doc/docs/.vitepress/theme/custom.css
+++ b/doc/docs/.vitepress/theme/custom.css
@@ -19,6 +19,7 @@
19.code-output code { 19.code-output code {
20 background: #ffffff; 20 background: #ffffff;
21 color: #000000; 21 color: #000000;
22 font-size: 14px;
22} 23}
23 24
24.dark .code-output, 25.dark .code-output,
diff --git a/doc/docs/.vitepress/theme/index.ts b/doc/docs/.vitepress/theme/index.ts
index 398df17..c4ec3d7 100644
--- a/doc/docs/.vitepress/theme/index.ts
+++ b/doc/docs/.vitepress/theme/index.ts
@@ -1,5 +1,6 @@
1import DefaultTheme from 'vitepress/theme' 1import DefaultTheme from 'vitepress/theme'
2import type { Theme } from 'vitepress' 2import type { Theme } from 'vitepress'
3import { h } from 'vue'
3import './custom.css' 4import './custom.css'
4 5
5// @ts-ignore 6// @ts-ignore
@@ -11,6 +12,10 @@ import YueDisplay from './components/YueDisplay.vue'
11 12
12const theme: Theme = { 13const theme: Theme = {
13 extends: DefaultTheme, 14 extends: DefaultTheme,
15 Layout: () =>
16 h(DefaultTheme.Layout, null, {
17 'layout-bottom': () => h(CompilerModal)
18 }),
14 enhanceApp({ app }) { 19 enhanceApp({ app }) {
15 app.component('CompilerModal', CompilerModal) 20 app.component('CompilerModal', CompilerModal)
16 app.component('YueCompiler', YueCompiler) 21 app.component('YueCompiler', YueCompiler)
diff --git a/doc/docs/doc/assignment.md b/doc/docs/doc/assignment.md
new file mode 100644
index 0000000..4dac6f4
--- /dev/null
+++ b/doc/docs/doc/assignment.md
@@ -0,0 +1,138 @@
1# Assignment
2
3The variable is dynamic typed and is defined as local by default. But you can change the scope of declaration by **local** and **global** statement.
4
5```yuescript
6hello = "world"
7a, b, c = 1, 2, 3
8hello = 123 -- uses the existing variable
9```
10<YueDisplay>
11
12```yue
13hello = "world"
14a, b, c = 1, 2, 3
15hello = 123 -- uses the existing variable
16```
17
18</YueDisplay>
19
20## Perform Update
21
22You can perform update assignment with many binary operators.
23```yuescript
24x = 1
25x += 1
26x -= 1
27x *= 10
28x /= 10
29x %= 10
30s ..= "world" -- will add a new local if local variable is not exist
31arg or= "default value"
32```
33<YueDisplay>
34
35```yue
36x = 1
37x += 1
38x -= 1
39x *= 10
40x /= 10
41x %= 10
42s ..= "world" -- will add a new local if local variable is not exist
43arg or= "default value"
44```
45
46</YueDisplay>
47
48## Chaining Assignment
49
50You can do chaining assignment to assign multiple items to hold the same value.
51```yuescript
52a = b = c = d = e = 0
53x = y = z = f!
54```
55<YueDisplay>
56
57```yue
58a = b = c = d = e = 0
59x = y = z = f!
60```
61
62</YueDisplay>
63
64## Explicit Locals
65```yuescript
66do
67 local a = 1
68 local *
69 print "forward declare all variables as locals"
70 x = -> 1 + y + z
71 y, z = 2, 3
72 global instance = Item\new!
73
74do
75 local X = 1
76 local ^
77 print "only forward declare upper case variables"
78 a = 1
79 B = 2
80```
81<YueDisplay>
82
83```yue
84do
85 local a = 1
86 local *
87 print "forward declare all variables as locals"
88 x = -> 1 + y + z
89 y, z = 2, 3
90 global instance = Item\new!
91
92do
93 local X = 1
94 local ^
95 print "only forward declare upper case variables"
96 a = 1
97 B = 2
98```
99
100</YueDisplay>
101
102## Explicit Globals
103```yuescript
104do
105 global a = 1
106 global *
107 print "declare all variables as globals"
108 x = -> 1 + y + z
109 y, z = 2, 3
110
111do
112 global X = 1
113 global ^
114 print "only declare upper case variables as globals"
115 a = 1
116 B = 2
117 local Temp = "a local value"
118```
119<YueDisplay>
120
121```yue
122do
123 global a = 1
124 global *
125 print "declare all variables as globals"
126 x = -> 1 + y + z
127 y, z = 2, 3
128
129do
130 global X = 1
131 global ^
132 print "only declare upper case variables as globals"
133 a = 1
134 B = 2
135 local Temp = "a local value"
136```
137
138</YueDisplay>
diff --git a/doc/docs/doc/attributes.md b/doc/docs/doc/attributes.md
new file mode 100644
index 0000000..e6fd5a7
--- /dev/null
+++ b/doc/docs/doc/attributes.md
@@ -0,0 +1,46 @@
1# Attributes
2
3Syntax 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.
4
5```yuescript
6const a = 123
7close _ = <close>: -> print "Out of scope."
8```
9<YueDisplay>
10
11```yue
12const a = 123
13close _ = <close>: -> print "Out of scope."
14```
15
16</YueDisplay>
17
18You can do desctructuring with variables attributed as constant.
19
20```yuescript
21const {:a, :b, c, d} = tb
22-- a = 1
23```
24<YueDisplay>
25
26```yue
27const {:a, :b, c, d} = tb
28-- a = 1
29```
30
31</YueDisplay>
32
33You can also declare a global variable to be `const`.
34
35```yuescript
36global const Constant = 123
37-- Constant = 1
38```
39<YueDisplay>
40
41```yue
42global const Constant = 123
43-- Constant = 1
44```
45
46</YueDisplay>
diff --git a/doc/docs/doc/backcalls.md b/doc/docs/doc/backcalls.md
new file mode 100644
index 0000000..e34331e
--- /dev/null
+++ b/doc/docs/doc/backcalls.md
@@ -0,0 +1,69 @@
1# Backcalls
2
3Backcalls 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.
4
5```yuescript
6x <- f
7print "hello" .. x
8```
9<YueDisplay>
10
11```yue
12x <- f
13print "hello" .. x
14```
15
16</YueDisplay>
17
18Fat arrow functions are also available.
19
20```yuescript
21<= f
22print @value
23```
24<YueDisplay>
25
26```yue
27<= f
28print @value
29```
30
31</YueDisplay>
32
33You can specify a placeholder for where you want the backcall function to go as a parameter.
34
35```yuescript
36(x) <- map _, [1, 2, 3]
37x * 2
38```
39<YueDisplay>
40
41```yue
42(x) <- map _, [1, 2, 3]
43x * 2
44```
45
46</YueDisplay>
47
48If 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.
49
50```yuescript
51result, msg = do
52 data <- readAsync "filename.txt"
53 print data
54 info <- processAsync data
55 check info
56print result, msg
57```
58<YueDisplay>
59
60```yue
61result, msg = do
62 data <- readAsync "filename.txt"
63 print data
64 info <- processAsync data
65 check info
66print result, msg
67```
68
69</YueDisplay>
diff --git a/doc/docs/doc/comment.md b/doc/docs/doc/comment.md
new file mode 100644
index 0000000..b67c97d
--- /dev/null
+++ b/doc/docs/doc/comment.md
@@ -0,0 +1,30 @@
1# Comment
2
3```yuescript
4-- I am a comment
5
6str = --[[
7This is a multi-line comment.
8It's OK.
9]] strA \ -- comment 1
10 .. strB \ -- comment 2
11 .. strC
12
13func --[[port]] 3000, --[[ip]] "192.168.1.1"
14```
15<YueDisplay>
16
17```yue
18-- I am a comment
19
20str = --[[
21This is a multi-line comment.
22It's OK.
23]] strA \ -- comment 1
24 .. strB \ -- comment 2
25 .. strC
26
27func --[[port]] 3000, --[[ip]] "192.168.1.1"
28```
29
30</YueDisplay>
diff --git a/doc/docs/doc/comprehensions.md b/doc/docs/doc/comprehensions.md
new file mode 100644
index 0000000..3a92167
--- /dev/null
+++ b/doc/docs/doc/comprehensions.md
@@ -0,0 +1,271 @@
1# Comprehensions
2
3Comprehensions provide a convenient syntax for constructing a new table by iterating over some existing object and applying an expression to its values. There are two kinds of comprehensions: list comprehensions and table comprehensions. They both produce Lua tables; list comprehensions accumulate values into an array-like table, and table comprehensions let you set both the key and the value on each iteration.
4
5## List Comprehensions
6
7The following creates a copy of the items table but with all the values doubled.
8
9```yuescript
10items = [ 1, 2, 3, 4 ]
11doubled = [item * 2 for i, item in ipairs items]
12```
13<YueDisplay>
14
15```yue
16items = [ 1, 2, 3, 4 ]
17doubled = [item * 2 for i, item in ipairs items]
18```
19
20</YueDisplay>
21
22The items included in the new table can be restricted with a when clause:
23
24```yuescript
25slice = [item for i, item in ipairs items when i > 1 and i < 3]
26```
27<YueDisplay>
28
29```yue
30slice = [item for i, item in ipairs items when i > 1 and i < 3]
31```
32
33</YueDisplay>
34
35Because it is common to iterate over the values of a numerically indexed table, an **\*** operator is introduced. The doubled example can be rewritten as:
36
37```yuescript
38doubled = [item * 2 for item in *items]
39```
40<YueDisplay>
41
42```yue
43doubled = [item * 2 for item in *items]
44```
45
46</YueDisplay>
47
48In list comprehensions, you can also use the spread operator `...` to flatten nested lists, achieving a flat map effect:
49
50```yuescript
51data =
52 a: [1, 2, 3]
53 b: [4, 5, 6]
54
55flat = [...v for k,v in pairs data]
56-- flat is now [1, 2, 3, 4, 5, 6]
57```
58<YueDisplay>
59
60```yue
61data =
62 a: [1, 2, 3]
63 b: [4, 5, 6]
64
65flat = [...v for k,v in pairs data]
66-- flat is now [1, 2, 3, 4, 5, 6]
67```
68
69</YueDisplay>
70
71The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause.
72
73Using multiple for clauses is the same as using nested loops:
74
75```yuescript
76x_coords = [4, 5, 6, 7]
77y_coords = [9, 2, 3]
78
79points = [ [x, y] for x in *x_coords \
80for y in *y_coords]
81```
82<YueDisplay>
83
84```yue
85x_coords = [4, 5, 6, 7]
86y_coords = [9, 2, 3]
87
88points = [ [x, y] for x in *x_coords \
89for y in *y_coords]
90```
91
92</YueDisplay>
93
94Numeric for loops can also be used in comprehensions:
95
96```yuescript
97evens = [i for i = 1, 100 when i % 2 == 0]
98```
99<YueDisplay>
100
101```yue
102evens = [i for i = 1, 100 when i % 2 == 0]
103```
104
105</YueDisplay>
106
107## Table Comprehensions
108
109The syntax for table comprehensions is very similar, only differing by using **{** and **}** and taking two values from each iteration.
110
111This example makes a copy of the tablething:
112
113```yuescript
114thing = {
115 color: "red"
116 name: "fast"
117 width: 123
118}
119
120thing_copy = {k, v for k, v in pairs thing}
121```
122<YueDisplay>
123
124```yue
125thing = {
126 color: "red"
127 name: "fast"
128 width: 123
129}
130
131thing_copy = {k, v for k, v in pairs thing}
132```
133
134</YueDisplay>
135
136```yuescript
137no_color = {k, v for k, v in pairs thing when k != "color"}
138```
139<YueDisplay>
140
141```yue
142no_color = {k, v for k, v in pairs thing when k != "color"}
143```
144
145</YueDisplay>
146
147The **\*** operator is also supported. Here we create a square root look up table for a few numbers.
148
149```yuescript
150numbers = [1, 2, 3, 4]
151sqrts = {i, math.sqrt i for i in *numbers}
152```
153<YueDisplay>
154
155```yue
156numbers = [1, 2, 3, 4]
157sqrts = {i, math.sqrt i for i in *numbers}
158```
159
160</YueDisplay>
161
162The key-value tuple in a table comprehension can also come from a single expression, in which case the expression should return two values. The first is used as the key and the second is used as the value:
163
164In this example we convert an array of pairs to a table where the first item in the pair is the key and the second is the value.
165
166```yuescript
167tuples = [ ["hello", "world"], ["foo", "bar"]]
168tbl = {unpack tuple for tuple in *tuples}
169```
170<YueDisplay>
171
172```yue
173tuples = [ ["hello", "world"], ["foo", "bar"]]
174tbl = {unpack tuple for tuple in *tuples}
175```
176
177</YueDisplay>
178
179## Slicing
180
181A special syntax is provided to restrict the items that are iterated over when using the **\*** operator. This is equivalent to setting the iteration bounds and a step size in a for loop.
182
183Here we can set the minimum and maximum bounds, taking all items with indexes between 1 and 5 inclusive:
184
185```yuescript
186slice = [item for item in *items[1, 5]]
187```
188<YueDisplay>
189
190```yue
191slice = [item for item in *items[1, 5]]
192```
193
194</YueDisplay>
195
196Any of the slice arguments can be left off to use a sensible default. In this example, if the max index is left off it defaults to the length of the table. This will take everything but the first element:
197
198```yuescript
199slice = [item for item in *items[2,]]
200```
201<YueDisplay>
202
203```yue
204slice = [item for item in *items[2,]]
205```
206
207</YueDisplay>
208
209If the minimum bound is left out, it defaults to 1. Here we only provide a step size and leave the other bounds blank. This takes all odd indexed items: (1, 3, 5, …)
210
211```yuescript
212slice = [item for item in *items[,,2]]
213```
214<YueDisplay>
215
216```yue
217slice = [item for item in *items[,,2]]
218```
219
220</YueDisplay>
221
222Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table.
223
224```yuescript
225-- take the last 4 items
226slice = [item for item in *items[-4,-1]]
227```
228<YueDisplay>
229
230```yue
231-- take the last 4 items
232slice = [item for item in *items[-4,-1]]
233```
234
235</YueDisplay>
236
237The step size can also be negative, which means that the items are taken in reverse order.
238
239```yuescript
240reverse_slice = [item for item in *items[-1,1,-1]]
241```
242<YueDisplay>
243
244```yue
245reverse_slice = [item for item in *items[-1,1,-1]]
246```
247
248</YueDisplay>
249
250### Slicing Expression
251
252Slicing can also be used as an expression. This is useful for getting a sub-list of a table.
253
254```yuescript
255-- take the 2nd and 4th items as a new list
256sub_list = items[2, 4]
257
258-- take the last 4 items
259last_four_items = items[-4, -1]
260```
261<YueDisplay>
262
263```yue
264-- take the 2nd and 4th items as a new list
265sub_list = items[2, 4]
266
267-- take the last 4 items
268last_four_items = items[-4, -1]
269```
270
271</YueDisplay>
diff --git a/doc/docs/doc/conditionals.md b/doc/docs/doc/conditionals.md
new file mode 100644
index 0000000..5ba81cf
--- /dev/null
+++ b/doc/docs/doc/conditionals.md
@@ -0,0 +1,149 @@
1# Conditionals
2
3```yuescript
4have_coins = false
5if have_coins
6 print "Got coins"
7else
8 print "No coins"
9```
10<YueDisplay>
11
12```yue
13have_coins = false
14if have_coins
15 print "Got coins"
16else
17 print "No coins"
18```
19
20</YueDisplay>
21
22A short syntax for single statements can also be used:
23
24```yuescript
25have_coins = false
26if have_coins then print "Got coins" else print "No coins"
27```
28<YueDisplay>
29
30```yue
31have_coins = false
32if have_coins then print "Got coins" else print "No coins"
33```
34
35</YueDisplay>
36
37Because if statements can be used as expressions, this can also be written as:
38
39```yuescript
40have_coins = false
41print if have_coins then "Got coins" else "No coins"
42```
43<YueDisplay>
44
45```yue
46have_coins = false
47print if have_coins then "Got coins" else "No coins"
48```
49
50</YueDisplay>
51
52Conditionals can also be used in return statements and assignments:
53
54```yuescript
55is_tall = (name) ->
56 if name == "Rob"
57 true
58 else
59 false
60
61message = if is_tall "Rob"
62 "I am very tall"
63else
64 "I am not so tall"
65
66print message -- prints: I am very tall
67```
68<YueDisplay>
69
70```yue
71is_tall = (name) ->
72 if name == "Rob"
73 true
74 else
75 false
76
77message = if is_tall "Rob"
78 "I am very tall"
79else
80 "I am not so tall"
81
82print message -- prints: I am very tall
83```
84
85</YueDisplay>
86
87The opposite of if is unless:
88
89```yuescript
90unless os.date("%A") == "Monday"
91 print "it is not Monday!"
92```
93<YueDisplay>
94
95```yue
96unless os.date("%A") == "Monday"
97 print "it is not Monday!"
98```
99
100</YueDisplay>
101
102```yuescript
103print "You're lucky!" unless math.random! > 0.1
104```
105<YueDisplay>
106
107```yue
108print "You're lucky!" unless math.random! > 0.1
109```
110
111</YueDisplay>
112
113## In Expression
114
115You can write range checking code with an `in-expression`.
116
117```yuescript
118a = 5
119
120if a in [1, 3, 5, 7]
121 print "checking equality with discrete values"
122
123if a in list
124 print "checking if `a` is in a list"
125```
126<YueDisplay>
127
128```yue
129a = 5
130
131if a in [1, 3, 5, 7]
132 print "checking equality with discrete values"
133
134if a in list
135 print "checking if `a` is in a list"
136```
137
138</YueDisplay>
139
140```yuescript
141print "You're lucky!" unless math.random! > 0.1
142```
143<YueDisplay>
144
145```yue
146print "You're lucky!" unless math.random! > 0.1
147```
148
149</YueDisplay>
diff --git a/doc/docs/doc/continue.md b/doc/docs/doc/continue.md
new file mode 100644
index 0000000..b000765
--- /dev/null
+++ b/doc/docs/doc/continue.md
@@ -0,0 +1,41 @@
1# Continue
2
3A continue statement can be used to skip the current iteration in a loop.
4
5```yuescript
6i = 0
7while i < 10
8 i += 1
9 continue if i % 2 == 0
10 print i
11```
12<YueDisplay>
13
14```yue
15i = 0
16while i < 10
17 i += 1
18 continue if i % 2 == 0
19 print i
20```
21
22</YueDisplay>
23
24continue can also be used with loop expressions to prevent that iteration from accumulating into the result. This examples filters the array table into just even numbers:
25
26```yuescript
27my_numbers = [1, 2, 3, 4, 5, 6]
28odds = for x in *my_numbers
29 continue if x % 2 == 1
30 x
31```
32<YueDisplay>
33
34```yue
35my_numbers = [1, 2, 3, 4, 5, 6]
36odds = for x in *my_numbers
37 continue if x % 2 == 1
38 x
39```
40
41</YueDisplay>
diff --git a/doc/docs/doc/destructuring-assignment.md b/doc/docs/doc/destructuring-assignment.md
new file mode 100644
index 0000000..8967eb3
--- /dev/null
+++ b/doc/docs/doc/destructuring-assignment.md
@@ -0,0 +1,240 @@
1# Destructuring Assignment
2
3Destructuring assignment is a way to quickly extract values from a table by their name or position in array based tables.
4
5Typically when you see a table literal, {1,2,3}, it is on the right hand side of an assignment because it is a value. Destructuring assignment swaps the role of the table literal, and puts it on the left hand side of an assign statement.
6
7This is best explained with examples. Here is how you would unpack the first two values from a table:
8
9```yuescript
10thing = [1, 2]
11
12[a, b] = thing
13print a, b
14```
15<YueDisplay>
16
17```yue
18thing = [1, 2]
19
20[a, b] = thing
21print a, b
22```
23
24</YueDisplay>
25
26In the destructuring table literal, the key represents the key to read from the right hand side, and the value represents the name the read value will be assigned to.
27
28```yuescript
29obj = {
30 hello: "world"
31 day: "tuesday"
32 length: 20
33}
34
35{hello: hello, day: the_day} = obj
36print hello, the_day
37
38:day = obj -- OK to do simple destructuring without braces
39```
40<YueDisplay>
41
42```yue
43obj = {
44 hello: "world"
45 day: "tuesday"
46 length: 20
47}
48
49{hello: hello, day: the_day} = obj
50print hello, the_day
51
52:day = obj -- OK to do simple destructuring without braces
53```
54
55</YueDisplay>
56
57This also works with nested data structures as well:
58
59```yuescript
60obj2 = {
61 numbers: [1, 2, 3, 4]
62 properties: {
63 color: "green"
64 height: 13.5
65 }
66}
67
68{numbers: [first, second], properties: {color: color}} = obj2
69print first, second, color
70```
71<YueDisplay>
72
73```yue
74obj2 = {
75 numbers: [1, 2, 3, 4]
76 properties: {
77 color: "green"
78 height: 13.5
79 }
80}
81
82{numbers: [first, second]} = obj2
83print first, second, color
84```
85
86</YueDisplay>
87
88If the destructuring statement is complicated, feel free to spread it out over a few lines. A slightly more complicated example:
89
90```yuescript
91{
92 numbers: [first, second]
93 properties: {
94 color: color
95 }
96} = obj2
97```
98<YueDisplay>
99
100```yue
101{
102 numbers: [first, second]
103 properties: {
104 color: color
105 }
106} = obj2
107```
108
109</YueDisplay>
110
111It'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:
112
113```yuescript
114{:concat, :insert} = table
115```
116<YueDisplay>
117
118```yue
119{:concat, :insert} = table
120```
121
122</YueDisplay>
123
124This is effectively the same as import, but we can rename fields we want to extract by mixing the syntax:
125
126```yuescript
127{:mix, :max, random: rand} = math
128```
129<YueDisplay>
130
131```yue
132{:mix, :max, random: rand} = math
133```
134
135</YueDisplay>
136
137You can write default values while doing destructuring like:
138
139```yuescript
140{:name = "nameless", :job = "jobless"} = person
141```
142<YueDisplay>
143
144```yue
145{:name = "nameless", :job = "jobless"} = person
146```
147
148</YueDisplay>
149
150You can use `_` as placeholder when doing a list destructuring:
151
152```yuescript
153[_, two, _, four] = items
154```
155<YueDisplay>
156
157```yue
158[_, two, _, four] = items
159```
160
161</YueDisplay>
162
163## Range Destructuring
164
165You 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.
166
167```yuescript
168orders = ["first", "second", "third", "fourth", "last"]
169[first, ...bulk, last] = orders
170print first -- prints: first
171print bulk -- prints: {"second", "third", "fourth"}
172print last -- prints: last
173```
174<YueDisplay>
175
176```yue
177orders = ["first", "second", "third", "fourth", "last"]
178[first, ...bulk, last] = orders
179print first -- prints: first
180print bulk -- prints: {"second", "third", "fourth"}
181print last -- prints: last
182```
183
184</YueDisplay>
185
186The 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:
187
188```yuescript
189-- Capture everything after first element
190[first, ...rest] = orders
191
192-- Capture everything before last element
193[...start, last] = orders
194
195-- Capture things except the middle elements
196[first, ..._, last] = orders
197```
198<YueDisplay>
199
200```yue
201-- Capture everything after first element
202[first, ...rest] = orders
203
204-- Capture everything before last element
205[...start, last] = orders
206
207-- Capture things except the middle elements
208[first, ..._, last] = orders
209```
210
211</YueDisplay>
212
213## Destructuring In Other Places
214
215Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop:
216
217```yuescript
218tuples = [
219 ["hello", "world"]
220 ["egg", "head"]
221]
222
223for [left, right] in *tuples
224 print left, right
225```
226<YueDisplay>
227
228```yue
229tuples = [
230 ["hello", "world"]
231 ["egg", "head"]
232]
233
234for [left, right] in *tuples
235 print left, right
236```
237
238</YueDisplay>
239
240We know each element in the array table is a two item tuple, so we can unpack it directly in the names clause of the for statement using a destructure.
diff --git a/doc/docs/doc/do.md b/doc/docs/doc/do.md
new file mode 100644
index 0000000..4990d6f
--- /dev/null
+++ b/doc/docs/doc/do.md
@@ -0,0 +1,66 @@
1# Do
2
3When used as a statement, do works just like it does in Lua.
4
5```yuescript
6do
7 var = "hello"
8 print var
9print var -- nil here
10```
11<YueDisplay>
12
13```yue
14do
15 var = "hello"
16 print var
17print var -- nil here
18```
19
20</YueDisplay>
21
22YueScript'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.
23
24```yuescript
25counter = do
26 i = 0
27 ->
28 i += 1
29 i
30
31print counter!
32print counter!
33```
34<YueDisplay>
35
36```yue
37counter = do
38 i = 0
39 ->
40 i += 1
41 i
42
43print counter!
44print counter!
45```
46
47</YueDisplay>
48
49```yuescript
50tbl = {
51 key: do
52 print "assigning key!"
53 1234
54}
55```
56<YueDisplay>
57
58```yue
59tbl = {
60 key: do
61 print "assigning key!"
62 1234
63}
64```
65
66</YueDisplay>
diff --git a/doc/docs/doc/for-loop.md b/doc/docs/doc/for-loop.md
new file mode 100644
index 0000000..cabcde5
--- /dev/null
+++ b/doc/docs/doc/for-loop.md
@@ -0,0 +1,127 @@
1# For Loop
2
3There are two for loop forms, just like in Lua. A numeric one and a generic one:
4
5```yuescript
6for i = 10, 20
7 print i
8
9for k = 1, 15, 2 -- an optional step provided
10 print k
11
12for key, value in pairs object
13 print key, value
14```
15<YueDisplay>
16
17```yue
18for i = 10, 20
19 print i
20
21for k = 1, 15, 2 -- an optional step provided
22 print k
23
24for key, value in pairs object
25 print key, value
26```
27
28</YueDisplay>
29
30The slicing and **\*** operators can be used, just like with comprehensions:
31
32```yuescript
33for item in *items[2, 4]
34 print item
35```
36<YueDisplay>
37
38```yue
39for item in *items[2, 4]
40 print item
41```
42
43</YueDisplay>
44
45A shorter syntax is also available for all variations when the body is only a single line:
46
47```yuescript
48for item in *items do print item
49
50for j = 1, 10, 3 do print j
51```
52<YueDisplay>
53
54```yue
55for item in *items do print item
56
57for j = 1, 10, 3 do print j
58```
59
60</YueDisplay>
61
62A for loop can also be used as an expression. The last statement in the body of the for loop is coerced into an expression and appended to an accumulating array table.
63
64Doubling every even number:
65
66```yuescript
67doubled_evens = for i = 1, 20
68 if i % 2 == 0
69 i * 2
70 else
71 i
72```
73<YueDisplay>
74
75```yue
76doubled_evens = for i = 1, 20
77 if i % 2 == 0
78 i * 2
79 else
80 i
81```
82
83</YueDisplay>
84
85In 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.
86
87For example, to find the first number greater than 10:
88
89```yuescript
90first_large = for n in *numbers
91 break n if n > 10
92```
93<YueDisplay>
94
95```yue
96first_large = for n in *numbers
97 break n if n > 10
98```
99
100</YueDisplay>
101
102This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions.
103
104You can also filter values by combining the for loop expression with the continue statement.
105
106For 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.
107
108```yuescript
109func_a = -> for i = 1, 10 do print i
110func_b = -> return for i = 1, 10 do i
111
112print func_a! -- prints nil
113print func_b! -- prints table object
114```
115<YueDisplay>
116
117```yue
118func_a = -> for i = 1, 10 do print i
119func_b = -> return for i = 1, 10 do i
120
121print func_a! -- prints nil
122print func_b! -- prints table object
123```
124
125</YueDisplay>
126
127This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop.
diff --git a/doc/docs/doc/function-literals.md b/doc/docs/doc/function-literals.md
new file mode 100644
index 0000000..316e07c
--- /dev/null
+++ b/doc/docs/doc/function-literals.md
@@ -0,0 +1,494 @@
1# Function Literals
2
3All functions are created using a function expression. A simple function is denoted using the arrow: **->**.
4
5```yuescript
6my_function = ->
7my_function() -- call the empty function
8```
9<YueDisplay>
10
11```yue
12my_function = ->
13my_function() -- call the empty function
14```
15
16</YueDisplay>
17
18The body of the function can either be one statement placed directly after the arrow, or it can be a series of statements indented on the following lines:
19
20```yuescript
21func_a = -> print "hello world"
22
23func_b = ->
24 value = 100
25 print "The value:", value
26```
27<YueDisplay>
28
29```yue
30func_a = -> print "hello world"
31
32func_b = ->
33 value = 100
34 print "The value:", value
35```
36
37</YueDisplay>
38
39If a function has no arguments, it can be called using the ! operator, instead of empty parentheses. The ! invocation is the preferred way to call functions with no arguments.
40
41```yuescript
42func_a!
43func_b()
44```
45<YueDisplay>
46
47```yue
48func_a!
49func_b()
50```
51
52</YueDisplay>
53
54Functions with arguments can be created by preceding the arrow with a list of argument names in parentheses:
55
56```yuescript
57sum = (x, y) -> print "sum", x + y
58```
59<YueDisplay>
60
61```yue
62sum = (x, y) -> print "sum", x + y
63```
64
65</YueDisplay>
66
67Functions can be called by listing the arguments after the name of an expression that evaluates to a function. When chaining together function calls, the arguments are applied to the closest function to the left.
68
69```yuescript
70sum 10, 20
71print sum 10, 20
72
73a b c "a", "b", "c"
74```
75<YueDisplay>
76
77```yue
78sum 10, 20
79print sum 10, 20
80
81a b c "a", "b", "c"
82```
83
84</YueDisplay>
85
86In order to avoid ambiguity in when calling functions, parentheses can also be used to surround the arguments. This is required here in order to make sure the right arguments get sent to the right functions.
87
88```yuescript
89print "x:", sum(10, 20), "y:", sum(30, 40)
90```
91<YueDisplay>
92
93```yue
94print "x:", sum(10, 20), "y:", sum(30, 40)
95```
96
97</YueDisplay>
98
99There must not be any space between the opening parenthesis and the function.
100
101Functions will coerce the last statement in their body into a return statement, this is called implicit return:
102
103```yuescript
104sum = (x, y) -> x + y
105print "The sum is ", sum 10, 20
106```
107<YueDisplay>
108
109```yue
110sum = (x, y) -> x + y
111print "The sum is ", sum 10, 20
112```
113
114</YueDisplay>
115
116And if you need to explicitly return, you can use the return keyword:
117
118```yuescript
119sum = (x, y) -> return x + y
120```
121<YueDisplay>
122
123```yue
124sum = (x, y) -> return x + y
125```
126
127</YueDisplay>
128
129Just like in Lua, functions can return multiple values. The last statement must be a list of values separated by commas:
130
131```yuescript
132mystery = (x, y) -> x + y, x - y
133a, b = mystery 10, 20
134```
135<YueDisplay>
136
137```yue
138mystery = (x, y) -> x + y, x - y
139a, b = mystery 10, 20
140```
141
142</YueDisplay>
143
144## Fat Arrows
145
146Because it is an idiom in Lua to send an object as the first argument when calling a method, a special syntax is provided for creating functions which automatically includes a self argument.
147
148```yuescript
149func = (num) => @value + num
150```
151<YueDisplay>
152
153```yue
154func = (num) => @value + num
155```
156
157</YueDisplay>
158
159## Argument Defaults
160
161It is possible to provide default values for the arguments of a function. An argument is determined to be empty if its value is nil. Any nil arguments that have a default value will be replace before the body of the function is run.
162
163```yuescript
164my_function = (name = "something", height = 100) ->
165 print "Hello I am", name
166 print "My height is", height
167```
168<YueDisplay>
169
170```yue
171my_function = (name = "something", height = 100) ->
172 print "Hello I am", name
173 print "My height is", height
174```
175
176</YueDisplay>
177
178An argument default value expression is evaluated in the body of the function in the order of the argument declarations. For this reason default values have access to previously declared arguments.
179
180```yuescript
181some_args = (x = 100, y = x + 1000) ->
182 print x + y
183```
184<YueDisplay>
185
186```yue
187some_args = (x = 100, y = x + 1000) ->
188 print x + y
189```
190
191</YueDisplay>
192
193## Considerations
194
195Because of the expressive parentheses-less way of calling functions, some restrictions must be put in place to avoid parsing ambiguity involving whitespace.
196
197The minus sign plays two roles, a unary negation operator and a binary subtraction operator. Consider how the following examples compile:
198
199```yuescript
200a = x - 10
201b = x-10
202c = x -y
203d = x- z
204```
205<YueDisplay>
206
207```yue
208a = x - 10
209b = x-10
210c = x -y
211d = x- z
212```
213
214</YueDisplay>
215
216The precedence of the first argument of a function call can be controlled using whitespace if the argument is a literal string. In Lua, it is common to leave off parentheses when calling a function with a single string or table literal.
217
218When there is no space between a variable and a string literal, the function call takes precedence over any following expressions. No other arguments can be passed to the function when it is called this way.
219
220Where there is a space following a variable and a string literal, the function call acts as show above. The string literal belongs to any following expressions (if they exist), which serves as the argument list.
221
222```yuescript
223x = func"hello" + 100
224y = func "hello" + 100
225```
226<YueDisplay>
227
228```yue
229x = func"hello" + 100
230y = func "hello" + 100
231```
232
233</YueDisplay>
234
235## Multi-line arguments
236
237When calling functions that take a large number of arguments, it is convenient to split the argument list over multiple lines. Because of the white-space sensitive nature of the language, care must be taken when splitting up the argument list.
238
239If an argument list is to be continued onto the next line, the current line must end in a comma. And the following line must be indented more than the current indentation. Once indented, all other argument lines must be at the same level of indentation to be part of the argument list
240
241```yuescript
242my_func 5, 4, 3,
243 8, 9, 10
244
245cool_func 1, 2,
246 3, 4,
247 5, 6,
248 7, 8
249```
250<YueDisplay>
251
252```yue
253my_func 5, 4, 3,
254 8, 9, 10
255
256cool_func 1, 2,
257 3, 4,
258 5, 6,
259 7, 8
260```
261
262</YueDisplay>
263
264This type of invocation can be nested. The level of indentation is used to determine to which function the arguments belong to.
265
266```yuescript
267my_func 5, 6, 7,
268 6, another_func 6, 7, 8,
269 9, 1, 2,
270 5, 4
271```
272<YueDisplay>
273
274```yue
275my_func 5, 6, 7,
276 6, another_func 6, 7, 8,
277 9, 1, 2,
278 5, 4
279```
280
281</YueDisplay>
282
283Because tables also use the comma as a delimiter, this indentation syntax is helpful for letting values be part of the argument list instead of being part of the table.
284
285```yuescript
286x = [
287 1, 2, 3, 4, a_func 4, 5,
288 5, 6,
289 8, 9, 10
290]
291```
292<YueDisplay>
293
294```yue
295x = [
296 1, 2, 3, 4, a_func 4, 5,
297 5, 6,
298 8, 9, 10
299]
300```
301
302</YueDisplay>
303
304Although uncommon, notice how we can give a deeper indentation for function arguments if we know we will be using a lower indentation further on.
305
306```yuescript
307y = [ my_func 1, 2, 3,
308 4, 5,
309 5, 6, 7
310]
311```
312<YueDisplay>
313
314```yue
315y = [ my_func 1, 2, 3,
316 4, 5,
317 5, 6, 7
318]
319```
320
321</YueDisplay>
322
323The same thing can be done with other block level statements like conditionals. We can use indentation level to determine what statement a value belongs to:
324
325```yuescript
326if func 1, 2, 3,
327 "hello",
328 "world"
329 print "hello"
330 print "I am inside if"
331
332if func 1, 2, 3,
333 "hello",
334 "world"
335 print "hello"
336 print "I am inside if"
337```
338<YueDisplay>
339
340```yue
341if func 1, 2, 3,
342 "hello",
343 "world"
344 print "hello"
345 print "I am inside if"
346
347if func 1, 2, 3,
348 "hello",
349 "world"
350 print "hello"
351 print "I am inside if"
352```
353
354</YueDisplay>
355
356## Parameter Destructuring
357
358YueScript now supports destructuring function parameters when the argument is an object. Two forms of destructuring table literals are available:
359
360* **Curly-brace wrapped literals/object parameters**, allowing optional default values when fields are missing (e.g., `{:a, :b}`, `{a: a1 = 123}`).
361
362* **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.
363
364```yuescript
365f1 = (:a, :b, :c) ->
366 print a, b, c
367
368f1 a: 1, b: "2", c: {}
369
370f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
371 print a1, b, c
372
373arg1 = {a: 0}
374f2 arg1, arg2
375```
376<YueDisplay>
377
378```yue
379f1 = (:a, :b, :c) ->
380 print a, b, c
381
382f1 a: 1, b: "2", c: {}
383
384f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
385print a1, b, c
386
387arg1 = {a: 0}
388f2 arg1, arg2
389```
390
391</YueDisplay>
392
393## Prefixed Return Expression
394
395When 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:
396
397```yuescript
398findFirstEven = (list): nil ->
399 for item in *list
400 if type(item) == "table"
401 for sub in *item
402 if sub % 2 == 0
403 return sub
404```
405<YueDisplay>
406
407```yue
408findFirstEven = (list): nil ->
409 for item in *list
410 if type(item) == "table"
411 for sub in *item
412 if sub % 2 == 0
413 return sub
414```
415
416</YueDisplay>
417
418This is equivalent to:
419
420```yuescript
421findFirstEven = (list) ->
422 for item in *list
423 if type(item) == "table"
424 for sub in *item
425 if sub % 2 == 0
426 return sub
427 nil
428```
429<YueDisplay>
430
431```yue
432findFirstEven = (list) ->
433 for item in *list
434 if type(item) == "table"
435 for sub in *item
436 if sub % 2 == 0
437 return sub
438 nil
439```
440
441</YueDisplay>
442
443The 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.
444
445## Named Varargs
446
447You can use the `(...t) ->` syntax to automatically store varargs into a named table. This table will contain all passed arguments (including `nil` values), and the `n` field of the table will store the actual number of arguments passed (including `nil` values).
448
449```yuescript
450f = (...t) ->
451 print "argument count:", t.n
452 print "table length:", #t
453 for i = 1, t.n
454 print t[i]
455
456f 1, 2, 3
457f "a", "b", "c", "d"
458f!
459
460-- Handling cases with nil values
461process = (...args) ->
462 sum = 0
463 for i = 1, args.n
464 if args[i] != nil and type(args[i]) == "number"
465 sum += args[i]
466 sum
467
468process 1, nil, 3, nil, 5
469```
470<YueDisplay>
471
472```yue
473f = (...t) ->
474 print "argument count:", t.n
475 print "table length:", #t
476 for i = 1, t.n
477 print t[i]
478
479f 1, 2, 3
480f "a", "b", "c", "d"
481f!
482
483-- Handling cases with nil values
484process = (...args) ->
485 sum = 0
486 for i = 1, args.n
487 if args[i] != nil and type(args[i]) == "number"
488 sum += args[i]
489 sum
490
491process 1, nil, 3, nil, 5
492```
493
494</YueDisplay>
diff --git a/doc/docs/doc/function-stubs.md b/doc/docs/doc/function-stubs.md
new file mode 100644
index 0000000..57a8b0c
--- /dev/null
+++ b/doc/docs/doc/function-stubs.md
@@ -0,0 +1,48 @@
1# Function Stubs
2
3It is common to pass a function from an object around as a value, for example, passing an instance method into a function as a callback. If the function expects the object it is operating on as the first argument then you must somehow bundle that object with the function so it can be called properly.
4
5The function stub syntax is a shorthand for creating a new closure function that bundles both the object and function. This new function calls the wrapped function in the correct context of the object.
6
7Its syntax is the same as calling an instance method with the \ operator but with no argument list provided.
8
9```yuescript
10my_object = {
11 value: 1000
12 write: => print "the value:", @value
13}
14
15run_callback = (func) ->
16 print "running callback..."
17 func!
18
19-- this will not work:
20-- the function has to no reference to my_object
21run_callback my_object.write
22
23-- function stub syntax
24-- lets us bundle the object into a new function
25run_callback my_object\write
26```
27<YueDisplay>
28
29```yue
30my_object = {
31 value: 1000
32 write: => print "the value:", @value
33}
34
35run_callback = (func) ->
36 print "running callback..."
37 func!
38
39-- this will not work:
40-- the function has to no reference to my_object
41run_callback my_object.write
42
43-- function stub syntax
44-- lets us bundle the object into a new function
45run_callback my_object\write
46```
47
48</YueDisplay>
diff --git a/doc/docs/doc/if-assignment.md b/doc/docs/doc/if-assignment.md
new file mode 100644
index 0000000..02984e8
--- /dev/null
+++ b/doc/docs/doc/if-assignment.md
@@ -0,0 +1,72 @@
1# If Assignment
2
3`if` and `elseif` blocks can take an assignment in place of a conditional expression. Upon evaluating the conditional, the assignment will take place and the value that was assigned to will be used as the conditional expression. The assigned variable is only in scope for the body of the conditional, meaning it is never available if the value is not truthy. And you have to use "the walrus operator" `:=` instead of `=` to do assignment.
4
5```yuescript
6if user := database.find_user "moon"
7 print user.name
8```
9<YueDisplay>
10
11```yue
12if user := database.find_user "moon"
13 print user.name
14```
15
16</YueDisplay>
17
18```yuescript
19if hello := os.getenv "hello"
20 print "You have hello", hello
21elseif world := os.getenv "world"
22 print "you have world", world
23else
24 print "nothing :("
25```
26<YueDisplay>
27
28```yue
29if hello := os.getenv "hello"
30 print "You have hello", hello
31elseif world := os.getenv "world"
32 print "you have world", world
33else
34 print "nothing :("
35```
36
37</YueDisplay>
38
39If assignment with multiple return values. Only the first value is getting checked, other values are scoped.
40```yuescript
41if success, result := pcall -> "get result without problems"
42 print result -- variable result is scoped
43print "OK"
44```
45<YueDisplay>
46
47```yue
48if success, result := pcall -> "get result without problems"
49 print result -- variable result is scoped
50print "OK"
51```
52
53</YueDisplay>
54
55## While Assignment
56
57You can also use if assignment in a while loop to get the value as the loop condition.
58
59```yuescript
60while byte := stream\read_one!
61 -- do something with the byte
62 print byte
63```
64<YueDisplay>
65
66```yue
67while byte := stream\read_one!
68 -- do something with the byte
69 print byte
70```
71
72</YueDisplay>
diff --git a/doc/docs/doc/index.md b/doc/docs/doc/index.md
index 6de2ce7..b7f609b 100755
--- a/doc/docs/doc/index.md
+++ b/doc/docs/doc/index.md
@@ -1,5520 +1,11 @@
1--- 1---
2sidebar: auto
3title: Reference 2title: Reference
4--- 3---
5 4
6# YueScript 5# YueScript Documentation
7 6
8<img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em;"/> 7<img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em; padding-bottom: 2em;"/>
9 8
10## Introduction 9Welcome to the <b>YueScript</b> official documentation!<br/>
11 10Here you can find the language features, usage, reference examples and resources.<br/>
12YueScript is a dynamic language that compiles to Lua. And it's a [MoonScript](https://github.com/leafo/moonscript) dialect. The codes written in YueScript are expressive and extremely concise. And it is suitable for writing some changing application logic with more maintainable codes and runs in a Lua embeded environment such as games or website servers. 11Please select a chapter from the sidebar to start learning about YueScript.
13
14Yue (月) is the name of moon in Chinese and it's pronounced as [jyɛ].
15
16### An Overview of YueScript
17```yuescript
18-- import syntax
19import p, to_lua from "yue"
20
21-- object literals
22inventory =
23 equipment:
24 - "sword"
25 - "shield"
26 items:
27 - name: "potion"
28 count: 10
29 - name: "bread"
30 count: 3
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
42-- pipe operator
43[1, 2, 3]
44 |> map (x) -> x * 2
45 |> filter (x) -> x > 4
46 |> reduce 0, (a, b) -> a + b
47 |> print
48
49-- metatable manipulation
50apple =
51 size: 15
52 <index>:
53 color: 0x00ffff
54
55with apple
56 p .size, .color, .<index> if .<>?
57
58-- js-like export syntax
59export 🌛 = "月之脚本"
60```
61
62<YueDisplay>
63
64```yue
65-- import syntax
66import p, to_lua from "yue"
67
68-- object literals
69inventory =
70 equipment:
71 - "sword"
72 - "shield"
73 items:
74 - name: "potion"
75 count: 10
76 - name: "bread"
77 count: 3
78
79-- list comprehension
80map = (arr, action) ->
81 [action item for item in *arr]
82
83filter = (arr, cond) ->
84 [item for item in *arr when cond item]
85
86reduce = (arr, init, action): init ->
87 init = action init, item for item in *arr
88
89-- pipe operator
90[1, 2, 3]
91 |> map (x) -> x * 2
92 |> filter (x) -> x > 4
93 |> reduce 0, (a, b) -> a + b
94 |> print
95
96-- metatable manipulation
97apple =
98 size: 15
99 <index>:
100 color: 0x00ffff
101
102with apple
103 p .size, .color, .<index> if .<>?
104
105-- js-like export syntax
106export 🌛 = "月之脚本"
107```
108
109</YueDisplay>
110
111## Installation
112
113* **Lua Module**
114
115&emsp;Install [luarocks](https://luarocks.org), a package manager for Lua modules. Then install it as a Lua module and executable with:
116
117```
118> luarocks install yuescript
119```
120
121&emsp;Or you can build `yue.so` file with:
122
123```
124> make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua
125```
126
127&emsp;Then get the binary file from path **bin/shared/yue.so**.
128
129* **Build Binary Tool**
130
131&emsp;Clone this repo, then build and install executable with:
132```
133> make install
134```
135
136&emsp;Build YueScript tool without macro feature:
137```
138> make install NO_MACRO=true
139```
140
141&emsp;Build YueScript tool without built-in Lua binary:
142```
143> make install NO_LUA=true
144```
145
146* **Download Precompiled Binary**
147
148&emsp;You can download precompiled binary files, including binary executable files compatible with different Lua versions and library files.
149
150&emsp;Download precompiled binary files from [here](https://github.com/IppClub/YueScript/releases).
151
152## Usage
153
154### Lua Module
155
156&emsp;Use YueScript module in Lua:
157
158* **Case 1**
159Require "your_yuescript_entry.yue" in Lua.
160```Lua
161require("yue")("your_yuescript_entry")
162```
163&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.
164
165* **Case 2**
166Require YueScript module and rewite message by hand.
167```lua
168local yue = require("yue")
169yue.insert_loader()
170local success, result = xpcall(function()
171 return require("yuescript_module_name")
172end, function(err)
173 return yue.traceback(err)
174end)
175```
176
177* **Case 3**
178Use the YueScript compiler function in Lua.
179```lua
180local yue = require("yue")
181local codes, err, globals = yue.to_lua([[
182f = ->
183 print "hello world"
184f!
185]],{
186 implicit_return_root = true,
187 reserve_line_number = true,
188 lint_global = true,
189 space_over_tab = false,
190 options = {
191 target = "5.4",
192 path = "/script"
193 }
194})
195```
196
197### YueScript Tool
198
199&emsp;Use YueScript tool with:
200```sh
201> yue -h
202Usage: yue
203 [options] [<file/directory>] ...
204 yue -e <code_or_file> [args...]
205 yue -w [<directory>] [options]
206 yue -
207
208Notes:
209 - '-' / '--' must be the first and only argument.
210 - '-o/--output' can not be used with multiple input files.
211 - '-w/--watch' can not be used with file input (directory only).
212 - with '-e/--execute', remaining tokens are treated as script args.
213
214Options:
215 -h, --help Show this help message and exit.
216 -e <str>, --execute <str> Execute a file or raw codes
217 -m, --minify Generate minified codes
218 -r, --rewrite Rewrite output to match original line numbers
219 -t <output_to>, --output-to <output_to>
220 Specify where to place compiled files
221 -o <file>, --output <file> Write output to file
222 -p, --print Write output to standard out
223 -b, --benchmark Dump compile time (doesn't write output)
224 -g, --globals Dump global variables used in NAME LINE COLUMN
225 -s, --spaces Use spaces in generated codes instead of tabs
226 -l, --line-numbers Write line numbers from source codes
227 -j, --no-implicit-return Disable implicit return at end of file
228 -c, --reserve-comments Reserve comments before statement from source codes
229 -w [<dir>], --watch [<dir>]
230 Watch changes and compile every file under directory
231 -v, --version Print version
232 - Read from standard in, print to standard out
233 (Must be first and only argument)
234 -- Same as '-' (kept for backward compatibility)
235
236 --target <version> Specify the Lua version that codes will be generated to
237 (version can only be 5.1 to 5.5)
238 --path <path_str> Append an extra Lua search path string to package.path
239 --<key>=<value> Pass compiler option in key=value form (existing behavior)
240
241 Execute without options to enter REPL, type symbol '$'
242 in a single line to start/stop multi-line mode
243```
244&emsp;&emsp;Use cases:
245
246&emsp;&emsp;Recursively compile every YueScript file with extension **.yue** under current path: **yue .**
247
248&emsp;&emsp;Compile and save results to a target path: **yue -t /target/path/ .**
249
250&emsp;&emsp;Compile and reserve debug info: **yue -l .**
251
252&emsp;&emsp;Compile and generate minified codes: **yue -m .**
253
254&emsp;&emsp;Execute raw codes: **yue -e 'print 123'**
255
256&emsp;&emsp;Execute a YueScript file: **yue -e main.yue**
257
258## Macro
259
260### Common Usage
261
262Macro function is used for evaluating a string in the compile time and insert the generated codes into final compilation.
263
264```yuescript
265macro PI2 = -> math.pi * 2
266area = $PI2 * 5
267
268macro HELLO = -> "'hello world'"
269print $HELLO
270
271macro config = (debugging) ->
272 global debugMode = debugging == "true"
273 ""
274
275macro asserts = (cond) ->
276 debugMode and "assert #{cond}" or ""
277
278macro assert = (cond) ->
279 debugMode and "assert #{cond}" or "#{cond}"
280
281$config true
282$asserts item ~= nil
283
284$config false
285value = $assert item
286
287-- the passed expressions are treated as strings
288macro and = (...) -> "#{ table.concat {...}, ' and ' }"
289if $and f1!, f2!, f3!
290 print "OK"
291```
292<YueDisplay>
293
294```yue
295macro PI2 = -> math.pi * 2
296area = $PI2 * 5
297
298macro HELLO = -> "'hello world'"
299print $HELLO
300
301macro config = (debugging) ->
302 global debugMode = debugging == "true"
303 ""
304
305macro asserts = (cond) ->
306 debugMode and "assert #{cond}" or ""
307
308macro assert = (cond) ->
309 debugMode and "assert #{cond}" or "#{cond}"
310
311$config true
312$asserts item ~= nil
313
314$config false
315value = $assert item
316
317-- the passed expressions are treated as strings
318macro and = (...) -> "#{ table.concat {...}, ' and ' }"
319if $and f1!, f2!, f3!
320 print "OK"
321```
322
323</YueDisplay>
324
325### Insert Raw Codes
326
327A macro function can either return a YueScript string or a config table containing Lua codes.
328```yuescript
329macro yueFunc = (var) -> "local #{var} = ->"
330$yueFunc funcA
331funcA = -> "fail to assign to the Yue macro defined variable"
332
333macro luaFunc = (var) -> {
334 code: "local function #{var}() end"
335 type: "lua"
336}
337$luaFunc funcB
338funcB = -> "fail to assign to the Lua macro defined variable"
339
340macro lua = (code) -> {
341 :code
342 type: "lua"
343}
344
345-- the raw string leading and ending symbols are auto trimed
346$lua[==[
347-- raw Lua codes insertion
348if cond then
349 print("output")
350end
351]==]
352```
353<YueDisplay>
354
355```yue
356macro yueFunc = (var) -> "local #{var} = ->"
357$yueFunc funcA
358funcA = -> "fail to assign to the Yue macro defined variable"
359
360macro luaFunc = (var) -> {
361 code: "local function #{var}() end"
362 type: "lua"
363}
364$luaFunc funcB
365funcB = -> "fail to assign to the Lua macro defined variable"
366
367macro lua = (code) -> {
368 :code
369 type: "lua"
370}
371
372-- the raw string leading and ending symbols are auto trimed
373$lua[==[
374-- raw Lua codes insertion
375if cond then
376 print("output")
377end
378]==]
379```
380
381</YueDisplay>
382
383### Export Macro
384
385Macro functions can be exported from a module and get imported in another module. You have to put export macro functions in a single file to be used, and only macro definition, macro importing and macro expansion in place can be put into the macro exporting module.
386```yuescript
387-- file: utils.yue
388export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
389export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
390export macro foreach = (items, action) -> "for _ in *#{items}
391 #{action}"
392
393-- file main.yue
394import "utils" as {
395 $, -- symbol to import all macros
396 $foreach: $each -- rename macro $foreach to $each
397}
398[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
399```
400<YueDisplay>
401
402```yue
403-- file: utils.yue
404export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
405export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
406export macro foreach = (items, action) -> "for _ in *#{items}
407 #{action}"
408-- file main.yue
409-- import function is not available in browser, try it in a real environment
410--[[
411import "utils" as {
412 $, -- symbol to import all macros
413 $foreach: $each -- rename macro $foreach to $each
414}
415[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
416]]
417```
418
419</YueDisplay>
420
421### Builtin Macro
422
423There are some builtin macros but you can override them by declaring macros with the same names.
424```yuescript
425print $FILE -- get string of current module name
426print $LINE -- get number 2
427```
428<YueDisplay>
429
430```yue
431print $FILE -- get string of current module name
432print $LINE -- get number 2
433```
434
435</YueDisplay>
436
437### Generating Macros with Macros
438
439In YueScript, macro functions allow you to generate code at compile time. By nesting macro functions, you can create more complex generation patterns. This feature enables you to define a macro function that generates another macro function, allowing for more dynamic code generation.
440
441```yuescript
442macro Enum = (...) ->
443 items = {...}
444 itemSet = {item, true for item in *items}
445 (item) ->
446 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
447 "\"#{item}\""
448
449macro BodyType = $Enum(
450 Static
451 Dynamic
452 Kinematic
453)
454
455print "Valid enum type:", $BodyType Static
456-- print "Compilation error with enum type:", $BodyType Unknown
457```
458
459<YueDisplay>
460
461```yue
462macro Enum = (...) ->
463 items = {...}
464 itemSet = {item, true for item in *items}
465 (item) ->
466 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
467 "\"#{item}\""
468
469macro BodyType = $Enum(
470 Static
471 Dynamic
472 Kinematic
473)
474
475print "Valid enum type:", $BodyType Static
476-- print "Compilation error with enum type:", $BodyType Unknown
477```
478
479</YueDisplay>
480
481### Argument Validation
482
483You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time.
484
485```yuescript
486macro printNumAndStr = (num `Num, str `String) -> |
487 print(
488 #{num}
489 #{str}
490 )
491
492$printNumAndStr 123, "hello"
493```
494<YueDisplay>
495
496```yue
497macro printNumAndStr = (num `Num, str `String) -> |
498 print(
499 #{num}
500 #{str}
501 )
502
503$printNumAndStr 123, "hello"
504```
505
506</YueDisplay>
507
508If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place.
509
510```yuescript
511macro printNumAndStr = (num, str) ->
512 error "expected Num as first argument" unless $is_ast Num, num
513 error "expected String as second argument" unless $is_ast String, str
514 "print(#{num}, #{str})"
515
516$printNumAndStr 123, "hello"
517```
518<YueDisplay>
519
520```yue
521macro printNumAndStr = (num, str) ->
522 error "expected Num as first argument" unless $is_ast Num, num
523 error "expected String as second argument" unless $is_ast String, str
524 "print(#{num}, #{str})"
525
526$printNumAndStr 123, "hello"
527```
528
529</YueDisplay>
530
531For 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).
532
533## Operator
534
535All 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.
536
537```yuescript
538tb\func! if tb ~= nil
539tb::func! if tb != nil
540```
541<YueDisplay>
542
543```yue
544tb\func! if tb ~= nil
545tb::func! if tb != nil
546```
547
548</YueDisplay>
549
550### Chaining Comparisons
551
552Comparisons can be arbitrarily chained:
553
554```yuescript
555print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
556-- output: true
557
558a = 5
559print 1 <= a <= 10
560-- output: true
561```
562<YueDisplay>
563
564```yue
565print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
566-- output: true
567
568a = 5
569print 1 <= a <= 10
570-- output: true
571```
572
573</YueDisplay>
574
575Note the evaluation behavior of chained comparisons:
576
577```yuescript
578v = (x) ->
579 print x
580 x
581
582print v(1) < v(2) <= v(3)
583--[[
584 output:
585 2
586 1
587 3
588 true
589]]
590
591print v(1) > v(2) <= v(3)
592--[[
593 output:
594 2
595 1
596 false
597]]
598```
599<YueDisplay>
600
601```yue
602v = (x) ->
603 print x
604 x
605
606print v(1) < v(2) <= v(3)
607--[[
608 output:
609 2
610 1
611 3
612 true
613]]
614
615print v(1) > v(2) <= v(3)
616--[[
617 output:
618 2
619 1
620 false
621]]
622```
623
624</YueDisplay>
625
626The middle expression is only evaluated once, rather than twice as it would be if the expression were written as `v(1) < v(2) and v(2) <= v(3)`. However, the order of evaluations in a chained comparison is undefined. It is strongly recommended not to use expressions with side effects (such as printing) in chained comparisons. If side effects are required, the short-circuit `and` operator should be used explicitly.
627
628### Table Appending
629The **[] =** operator is used to append values to tables.
630
631```yuescript
632tab = []
633tab[] = "Value"
634```
635<YueDisplay>
636
637```yue
638tab = []
639tab[] = "Value"
640```
641
642</YueDisplay>
643
644You can also use the spread operator `...` to append all elements from one list to another:
645
646```yuescript
647tbA = [1, 2, 3]
648tbB = [4, 5, 6]
649tbA[] = ...tbB
650-- tbA is now [1, 2, 3, 4, 5, 6]
651```
652<YueDisplay>
653
654```yue
655tbA = [1, 2, 3]
656tbB = [4, 5, 6]
657tbA[] = ...tbB
658-- tbA is now [1, 2, 3, 4, 5, 6]
659```
660
661</YueDisplay>
662
663### Table Spreading
664
665You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals.
666
667```yuescript
668parts =
669 * "shoulders"
670 * "knees"
671lyrics =
672 * "head"
673 * ...parts
674 * "and"
675 * "toes"
676
677copy = {...other}
678
679a = {1, 2, 3, x: 1}
680b = {4, 5, y: 1}
681merge = {...a, ...b}
682```
683<YueDisplay>
684
685```yue
686parts =
687 * "shoulders"
688 * "knees"
689lyrics =
690 * "head"
691 * ...parts
692 * "and"
693 * "toes"
694
695copy = {...other}
696
697a = {1, 2, 3, x: 1}
698b = {4, 5, y: 1}
699merge = {...a, ...b}
700```
701
702</YueDisplay>
703
704### Table Reversed Indexing
705
706You can use the **#** operator to get the last elements of a table.
707
708```yuescript
709last = data.items[#]
710second_last = data.items[#-1]
711data.items[#] = 1
712```
713<YueDisplay>
714
715```yue
716last = data.items[#]
717second_last = data.items[#-1]
718data.items[#] = 1
719```
720
721</YueDisplay>
722
723### Metatable
724
725The **<>** operator can be used as a shortcut for metatable manipulation.
726
727* **Metatable Creation**
728Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**.
729
730```yuescript
731mt = {}
732add = (right) => <>: mt, value: @value + right.value
733mt.__add = add
734
735a = <>: mt, value: 1
736 -- set field with variable of the same name
737b = :<add>, value: 2
738c = <add>: mt.__add, value: 3
739
740d = a + b + c
741print d.value
742
743close _ = <close>: -> print "out of scope"
744```
745<YueDisplay>
746
747```yue
748mt = {}
749add = (right) => <>: mt, value: @value + right.value
750mt.__add = add
751
752a = <>: mt, value: 1
753 -- set field with variable of the same name
754b = :<add>, value: 2
755c = <add>: mt.__add, value: 3
756
757d = a + b + c
758print d.value
759
760close _ = <close>: -> print "out of scope"
761```
762
763</YueDisplay>
764
765* **Metatable Accessing**
766Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**.
767
768```yuescript
769-- create with metatable containing field "value"
770tb = <"value">: 123
771tb.<index> = tb.<>
772print tb.value
773
774tb.<> = __index: {item: "hello"}
775print tb.item
776```
777<YueDisplay>
778
779```yue
780-- create with metatable containing field "value"
781tb = <"value">: 123
782tb.<index> = tb.<>
783print tb.value
784tb.<> = __index: {item: "hello"}
785print tb.item
786```
787
788</YueDisplay>
789
790* **Metatable Destructure**
791Destruct metatable with metamethod key surrounded by **<>**.
792
793```yuescript
794{item, :new, :<close>, <index>: getter} = tb
795print item, new, close, getter
796```
797<YueDisplay>
798
799```yue
800{item, :new, :<close>, <index>: getter} = tb
801print item, new, close, getter
802```
803
804</YueDisplay>
805
806### Existence
807
808The **?** operator can be used in a variety of contexts to check for existence.
809
810```yuescript
811func?!
812print abc?["hello world"]?.xyz
813
814x = tab?.value
815len = utf8?.len or string?.len or (o) -> #o
816
817if print and x?
818 print x
819
820with? io.open "test.txt", "w"
821 \write "hello"
822 \close!
823```
824<YueDisplay>
825
826```yue
827func?!
828print abc?["hello world"]?.xyz
829
830x = tab?.value
831len = utf8?.len or string?.len or (o) -> #o
832
833if print and x?
834 print x
835
836with? io.open "test.txt", "w"
837 \write "hello"
838 \close!
839```
840
841</YueDisplay>
842
843### Piping
844
845Instead of a series of nested function calls, you can pipe values with operator **|>**.
846
847```yuescript
848"hello" |> print
8491 |> print 2 -- insert pipe item as the first argument
8502 |> print 1, _, 3 -- pipe with a placeholder
851
852-- pipe expression in multiline
853readFile "example.txt"
854 |> extract language, {}
855 |> parse language
856 |> emit
857 |> render
858 |> print
859```
860<YueDisplay>
861
862```yue
863"hello" |> print
8641 |> print 2 -- insert pipe item as the first argument
8652 |> print 1, _, 3 -- pipe with a placeholder
866-- pipe expression in multiline
867readFile "example.txt"
868 |> extract language, {}
869 |> parse language
870 |> emit
871 |> render
872 |> print
873```
874
875</YueDisplay>
876
877### Nil Coalescing
878
879The nil-coalescing operator **??** returns the value of its left-hand operand if it isn't **nil**; otherwise, it evaluates the right-hand operand and returns its result. The **??** operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-nil.
880```yuescript
881local a, b, c, d
882a = b ?? c ?? d
883func a ?? {}
884
885a ??= false
886```
887<YueDisplay>
888
889```yue
890local a, b, c, d
891a = b ?? c ?? d
892func a ?? {}
893a ??= false
894```
895
896</YueDisplay>
897
898### Implicit Object
899
900You 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.
901
902```yuescript
903-- assignment with implicit object
904list =
905 * 1
906 * 2
907 * 3
908
909-- function call with implicit object
910func
911 * 1
912 * 2
913 * 3
914
915-- return with implicit object
916f = ->
917 return
918 * 1
919 * 2
920 * 3
921
922-- table with implicit object
923tb =
924 name: "abc"
925
926 values:
927 - "a"
928 - "b"
929 - "c"
930
931 objects:
932 - name: "a"
933 value: 1
934 func: => @value + 1
935 tb:
936 fieldA: 1
937
938 - name: "b"
939 value: 2
940 func: => @value + 2
941 tb: { }
942
943```
944<YueDisplay>
945
946```yue
947-- assignment with implicit object
948list =
949 * 1
950 * 2
951 * 3
952
953-- function call with implicit object
954func
955 * 1
956 * 2
957 * 3
958
959-- return with implicit object
960f = ->
961 return
962 * 1
963 * 2
964 * 3
965
966-- table with implicit object
967tb =
968 name: "abc"
969
970 values:
971 - "a"
972 - "b"
973 - "c"
974
975 objects:
976 - name: "a"
977 value: 1
978 func: => @value + 1
979 tb:
980 fieldA: 1
981
982 - name: "b"
983 value: 2
984 func: => @value + 2
985 tb: { }
986```
987
988</YueDisplay>
989
990## Module
991
992### Import
993
994The import statement is a syntax sugar for requiring a module or help extracting items from an imported module. The imported items are const by default.
995
996```yuescript
997-- used as table destructuring
998do
999 import insert, concat from table
1000 -- report error when assigning to insert, concat
1001 import C, Ct, Cmt from require "lpeg"
1002 -- shortcut for implicit requiring
1003 import x, y, z from 'mymodule'
1004 -- import with Python style
1005 from 'module' import a, b, c
1006
1007-- shortcut for requring a module
1008do
1009 import 'module'
1010 import 'module_x'
1011 import "d-a-s-h-e-s"
1012 import "module.part"
1013
1014-- requring module with aliasing or table destructuring
1015do
1016 import "player" as PlayerModule
1017 import "lpeg" as :C, :Ct, :Cmt
1018 import "export" as {one, two, Something:{umm:{ch}}}
1019```
1020<YueDisplay>
1021
1022```yue
1023-- used as table destructuring
1024do
1025 import insert, concat from table
1026 -- report error when assigning to insert, concat
1027 import C, Ct, Cmt from require "lpeg"
1028 -- shortcut for implicit requiring
1029 import x, y, z from 'mymodule'
1030 -- import with Python style
1031 from 'module' import a, b, c
1032
1033-- shortcut for requring a module
1034do
1035 import 'module'
1036 import 'module_x'
1037 import "d-a-s-h-e-s"
1038 import "module.part"
1039
1040-- requring module with aliasing or table destructuring
1041do
1042 import "player" as PlayerModule
1043 import "lpeg" as :C, :Ct, :Cmt
1044 import "export" as {one, two, Something:{umm:{ch}}}
1045```
1046
1047</YueDisplay>
1048
1049### Import Global
1050
1051You can import specific globals into local variables with `import`. When importing a chain of global variable accessings, the last field will be assigned to the local variable.
1052
1053```yuescript
1054do
1055 import tostring
1056 import table.concat
1057 print concat ["a", tostring 1]
1058```
1059<YueDisplay>
1060
1061```yue
1062do
1063 import tostring
1064 import table.concat
1065 print concat ["a", tostring 1]
1066```
1067
1068</YueDisplay>
1069
1070#### Automatic Import
1071
1072You can place `import global` at the top of a block to automatically import all names that have not been explicitly declared or assigned in the current scope as globals. These implicit imports are treated as local consts that reference the corresponding globals at the position of the statement.
1073
1074Names that are explicitly declared as globals in the same scope will not be imported, so you can still assign to them.
1075
1076```yuescript
1077do
1078 import global
1079 print "hello"
1080 math.random 3
1081 -- print = nil -- error: imported globals are const
1082
1083do
1084 -- explicit global variable will not be imported
1085 import global
1086 global FLAG
1087 print FLAG
1088 FLAG = 123
1089```
1090<YueDisplay>
1091
1092```yue
1093do
1094 import global
1095 print "hello"
1096 math.random 3
1097 -- print = nil -- error: imported globals are const
1098
1099do
1100 -- explicit global variable will not be imported
1101 import global
1102 global FLAG
1103 print FLAG
1104 FLAG = 123
1105```
1106
1107</YueDisplay>
1108
1109### Export
1110
1111The export statement offers a concise way to define modules.
1112
1113* **Named Export**
1114Named export will define a local variable as well as adding a field in the exported table.
1115
1116```yuescript
1117export a, b, c = 1, 2, 3
1118export cool = "cat"
1119
1120export What = if this
1121 "abc"
1122else
1123 "def"
1124
1125export y = ->
1126 hallo = 3434
1127
1128export class Something
1129 umm: "cool"
1130```
1131<YueDisplay>
1132
1133```yue
1134export a, b, c = 1, 2, 3
1135export cool = "cat"
1136
1137export What = if this
1138 "abc"
1139else
1140 "def"
1141
1142export y = ->
1143 hallo = 3434
1144
1145export class Something
1146 umm: "cool"
1147```
1148
1149</YueDisplay>
1150
1151Doing named export with destructuring.
1152
1153```yuescript
1154export :loadstring, to_lua: tolua = yue
1155export {itemA: {:fieldA = 'default'}} = tb
1156```
1157<YueDisplay>
1158
1159```yue
1160export :loadstring, to_lua: tolua = yue
1161export {itemA: {:fieldA = 'default'}} = tb
1162```
1163
1164</YueDisplay>
1165
1166Export named items from module without creating local variables.
1167
1168```yuescript
1169export.itemA = tb
1170export.<index> = items
1171export["a-b-c"] = 123
1172```
1173<YueDisplay>
1174
1175```yue
1176export.itemA = tb
1177export.<index> = items
1178export["a-b-c"] = 123
1179```
1180
1181</YueDisplay>
1182
1183* **Unnamed Export**
1184Unnamed export will add the target item into the array part of the exported table.
1185
1186```yuescript
1187d, e, f = 3, 2, 1
1188export d, e, f
1189
1190export if this
1191 123
1192else
1193 456
1194
1195export with tmp
1196 j = 2000
1197```
1198<YueDisplay>
1199
1200```yue
1201d, e, f = 3, 2, 1
1202export d, e, f
1203
1204export if this
1205 123
1206else
1207 456
1208
1209export with tmp
1210 j = 2000
1211```
1212
1213</YueDisplay>
1214
1215* **Default Export**
1216Using the **default** keyword in export statement to replace the exported table with any thing.
1217
1218```yuescript
1219export default ->
1220 print "hello"
1221 123
1222```
1223<YueDisplay>
1224
1225```yue
1226export default ->
1227 print "hello"
1228 123
1229```
1230
1231</YueDisplay>
1232
1233## Assignment
1234
1235The variable is dynamic typed and is defined as local by default. But you can change the scope of declaration by **local** and **global** statement.
1236
1237```yuescript
1238hello = "world"
1239a, b, c = 1, 2, 3
1240hello = 123 -- uses the existing variable
1241```
1242<YueDisplay>
1243
1244```yue
1245hello = "world"
1246a, b, c = 1, 2, 3
1247hello = 123 -- uses the existing variable
1248```
1249
1250</YueDisplay>
1251
1252### Perform Update
1253
1254You can perform update assignment with many binary operators.
1255```yuescript
1256x = 1
1257x += 1
1258x -= 1
1259x *= 10
1260x /= 10
1261x %= 10
1262s ..= "world" -- will add a new local if local variable is not exist
1263arg or= "default value"
1264```
1265<YueDisplay>
1266
1267```yue
1268x = 1
1269x += 1
1270x -= 1
1271x *= 10
1272x /= 10
1273x %= 10
1274s ..= "world" -- will add a new local if local variable is not exist
1275arg or= "default value"
1276```
1277
1278</YueDisplay>
1279
1280### Chaining Assignment
1281
1282You can do chaining assignment to assign multiple items to hold the same value.
1283```yuescript
1284a = b = c = d = e = 0
1285x = y = z = f!
1286```
1287<YueDisplay>
1288
1289```yue
1290a = b = c = d = e = 0
1291x = y = z = f!
1292```
1293
1294</YueDisplay>
1295
1296### Explicit Locals
1297```yuescript
1298do
1299 local a = 1
1300 local *
1301 print "forward declare all variables as locals"
1302 x = -> 1 + y + z
1303 y, z = 2, 3
1304 global instance = Item\new!
1305
1306do
1307 local X = 1
1308 local ^
1309 print "only forward declare upper case variables"
1310 a = 1
1311 B = 2
1312```
1313<YueDisplay>
1314
1315```yue
1316do
1317 local a = 1
1318 local *
1319 print "forward declare all variables as locals"
1320 x = -> 1 + y + z
1321 y, z = 2, 3
1322 global instance = Item\new!
1323
1324do
1325 local X = 1
1326 local ^
1327 print "only forward declare upper case variables"
1328 a = 1
1329 B = 2
1330```
1331
1332</YueDisplay>
1333
1334### Explicit Globals
1335```yuescript
1336do
1337 global a = 1
1338 global *
1339 print "declare all variables as globals"
1340 x = -> 1 + y + z
1341 y, z = 2, 3
1342
1343do
1344 global X = 1
1345 global ^
1346 print "only declare upper case variables as globals"
1347 a = 1
1348 B = 2
1349 local Temp = "a local value"
1350```
1351<YueDisplay>
1352
1353```yue
1354do
1355 global a = 1
1356 global *
1357 print "declare all variables as globals"
1358 x = -> 1 + y + z
1359 y, z = 2, 3
1360
1361do
1362 global X = 1
1363 global ^
1364 print "only declare upper case variables as globals"
1365 a = 1
1366 B = 2
1367 local Temp = "a local value"
1368```
1369
1370</YueDisplay>
1371
1372## Destructuring Assignment
1373
1374Destructuring assignment is a way to quickly extract values from a table by their name or position in array based tables.
1375
1376Typically when you see a table literal, {1,2,3}, it is on the right hand side of an assignment because it is a value. Destructuring assignment swaps the role of the table literal, and puts it on the left hand side of an assign statement.
1377
1378This is best explained with examples. Here is how you would unpack the first two values from a table:
1379
1380```yuescript
1381thing = [1, 2]
1382
1383[a, b] = thing
1384print a, b
1385```
1386<YueDisplay>
1387
1388```yue
1389thing = [1, 2]
1390
1391[a, b] = thing
1392print a, b
1393```
1394
1395</YueDisplay>
1396
1397In the destructuring table literal, the key represents the key to read from the right hand side, and the value represents the name the read value will be assigned to.
1398
1399```yuescript
1400obj = {
1401 hello: "world"
1402 day: "tuesday"
1403 length: 20
1404}
1405
1406{hello: hello, day: the_day} = obj
1407print hello, the_day
1408
1409:day = obj -- OK to do simple destructuring without braces
1410```
1411<YueDisplay>
1412
1413```yue
1414obj = {
1415 hello: "world"
1416 day: "tuesday"
1417 length: 20
1418}
1419
1420{hello: hello, day: the_day} = obj
1421print hello, the_day
1422
1423:day = obj -- OK to do simple destructuring without braces
1424```
1425
1426</YueDisplay>
1427
1428This also works with nested data structures as well:
1429
1430```yuescript
1431obj2 = {
1432 numbers: [1, 2, 3, 4]
1433 properties: {
1434 color: "green"
1435 height: 13.5
1436 }
1437}
1438
1439{numbers: [first, second], properties: {color: color}} = obj2
1440print first, second, color
1441```
1442<YueDisplay>
1443
1444```yue
1445obj2 = {
1446 numbers: [1, 2, 3, 4]
1447 properties: {
1448 color: "green"
1449 height: 13.5
1450 }
1451}
1452
1453{numbers: [first, second]} = obj2
1454print first, second, color
1455```
1456
1457</YueDisplay>
1458
1459If the destructuring statement is complicated, feel free to spread it out over a few lines. A slightly more complicated example:
1460
1461```yuescript
1462{
1463 numbers: [first, second]
1464 properties: {
1465 color: color
1466 }
1467} = obj2
1468```
1469<YueDisplay>
1470
1471```yue
1472{
1473 numbers: [first, second]
1474 properties: {
1475 color: color
1476 }
1477} = obj2
1478```
1479
1480</YueDisplay>
1481
1482It'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:
1483
1484```yuescript
1485{:concat, :insert} = table
1486```
1487<YueDisplay>
1488
1489```yue
1490{:concat, :insert} = table
1491```
1492
1493</YueDisplay>
1494
1495This is effectively the same as import, but we can rename fields we want to extract by mixing the syntax:
1496
1497```yuescript
1498{:mix, :max, random: rand} = math
1499```
1500<YueDisplay>
1501
1502```yue
1503{:mix, :max, random: rand} = math
1504```
1505
1506</YueDisplay>
1507
1508You can write default values while doing destructuring like:
1509
1510```yuescript
1511{:name = "nameless", :job = "jobless"} = person
1512```
1513<YueDisplay>
1514
1515```yue
1516{:name = "nameless", :job = "jobless"} = person
1517```
1518
1519</YueDisplay>
1520
1521You can use `_` as placeholder when doing a list destructuring:
1522
1523```yuescript
1524[_, two, _, four] = items
1525```
1526<YueDisplay>
1527
1528```yue
1529[_, two, _, four] = items
1530```
1531
1532</YueDisplay>
1533
1534### Range Destructuring
1535
1536You 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.
1537
1538```yuescript
1539orders = ["first", "second", "third", "fourth", "last"]
1540[first, ...bulk, last] = orders
1541print first -- prints: first
1542print bulk -- prints: {"second", "third", "fourth"}
1543print last -- prints: last
1544```
1545<YueDisplay>
1546
1547```yue
1548orders = ["first", "second", "third", "fourth", "last"]
1549[first, ...bulk, last] = orders
1550print first -- prints: first
1551print bulk -- prints: {"second", "third", "fourth"}
1552print last -- prints: last
1553```
1554
1555</YueDisplay>
1556
1557The 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:
1558
1559```yuescript
1560-- Capture everything after first element
1561[first, ...rest] = orders
1562
1563-- Capture everything before last element
1564[...start, last] = orders
1565
1566-- Capture things except the middle elements
1567[first, ..._, last] = orders
1568```
1569<YueDisplay>
1570
1571```yue
1572-- Capture everything after first element
1573[first, ...rest] = orders
1574
1575-- Capture everything before last element
1576[...start, last] = orders
1577
1578-- Capture things except the middle elements
1579[first, ..._, last] = orders
1580```
1581
1582</YueDisplay>
1583
1584### Destructuring In Other Places
1585
1586Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop:
1587
1588```yuescript
1589tuples = [
1590 ["hello", "world"]
1591 ["egg", "head"]
1592]
1593
1594for [left, right] in *tuples
1595 print left, right
1596```
1597<YueDisplay>
1598
1599```yue
1600tuples = [
1601 ["hello", "world"]
1602 ["egg", "head"]
1603]
1604
1605for [left, right] in *tuples
1606 print left, right
1607```
1608
1609</YueDisplay>
1610
1611We know each element in the array table is a two item tuple, so we can unpack it directly in the names clause of the for statement using a destructure.
1612
1613## If Assignment
1614
1615`if` and `elseif` blocks can take an assignment in place of a conditional expression. Upon evaluating the conditional, the assignment will take place and the value that was assigned to will be used as the conditional expression. The assigned variable is only in scope for the body of the conditional, meaning it is never available if the value is not truthy. And you have to use "the walrus operator" `:=` instead of `=` to do assignment.
1616
1617```yuescript
1618if user := database.find_user "moon"
1619 print user.name
1620```
1621<YueDisplay>
1622
1623```yue
1624if user := database.find_user "moon"
1625 print user.name
1626```
1627
1628</YueDisplay>
1629
1630```yuescript
1631if hello := os.getenv "hello"
1632 print "You have hello", hello
1633elseif world := os.getenv "world"
1634 print "you have world", world
1635else
1636 print "nothing :("
1637```
1638<YueDisplay>
1639
1640```yue
1641if hello := os.getenv "hello"
1642 print "You have hello", hello
1643elseif world := os.getenv "world"
1644 print "you have world", world
1645else
1646 print "nothing :("
1647```
1648
1649</YueDisplay>
1650
1651If assignment with multiple return values. Only the first value is getting checked, other values are scoped.
1652```yuescript
1653if success, result := pcall -> "get result without problems"
1654 print result -- variable result is scoped
1655print "OK"
1656```
1657<YueDisplay>
1658
1659```yue
1660if success, result := pcall -> "get result without problems"
1661 print result -- variable result is scoped
1662print "OK"
1663```
1664
1665</YueDisplay>
1666
1667### While Assignment
1668
1669You can also use if assignment in a while loop to get the value as the loop condition.
1670```yuescript
1671while byte := stream\read_one!
1672 -- do something with the byte
1673 print byte
1674```
1675<YueDisplay>
1676
1677```yue
1678while byte := stream\read_one!
1679 -- do something with the byte
1680 print byte
1681```
1682
1683</YueDisplay>
1684
1685## Varargs Assignment
1686
1687You can assign the results returned from a function to a varargs symbol `...`. And then access its content using the Lua way.
1688```yuescript
1689list = [1, 2, 3, 4, 5]
1690fn = (ok) -> ok, table.unpack list
1691ok, ... = fn true
1692count = select '#', ...
1693first = select 1, ...
1694print ok, count, first
1695```
1696<YueDisplay>
1697
1698```yue
1699list = [1, 2, 3, 4, 5]
1700fn = (ok) -> ok, table.unpack list
1701ok, ... = fn true
1702count = select '#', ...
1703first = select 1, ...
1704print ok, count, first
1705```
1706
1707</YueDisplay>
1708
1709## Whitespace
1710
1711YueScript is a whitespace significant language. You have to write some code block in the same indent with space **' '** or tab **'\t'** like function body, value list and some control blocks. And expressions containing different whitespaces might mean different things. Tab is treated like 4 space, but it's better not mix the use of spaces and tabs.
1712
1713### Statement Separator
1714
1715A statement normally ends at a line break. You can also use a semicolon `;` to explicitly terminate a statement, which allows writing multiple statements on the same line:
1716
1717```yuescript
1718a = 1; b = 2; print a + b
1719```
1720<YueDisplay>
1721
1722```yue
1723a = 1; b = 2; print a + b
1724```
1725
1726</YueDisplay>
1727
1728### Multiline Chaining
1729
1730You can write multi-line chaining function calls with a same indent.
1731```yuescript
1732Rx.Observable
1733 .fromRange 1, 8
1734 \filter (x) -> x % 2 == 0
1735 \concat Rx.Observable.of 'who do we appreciate'
1736 \map (value) -> value .. '!'
1737 \subscribe print
1738```
1739<YueDisplay>
1740
1741```yue
1742Rx.Observable
1743 .fromRange 1, 8
1744 \filter (x) -> x % 2 == 0
1745 \concat Rx.Observable.of 'who do we appreciate'
1746 \map (value) -> value .. '!'
1747 \subscribe print
1748```
1749
1750</YueDisplay>
1751
1752## Comment
1753
1754```yuescript
1755-- I am a comment
1756
1757str = --[[
1758This is a multi-line comment.
1759It's OK.
1760]] strA \ -- comment 1
1761 .. strB \ -- comment 2
1762 .. strC
1763
1764func --[[port]] 3000, --[[ip]] "192.168.1.1"
1765```
1766<YueDisplay>
1767
1768```yue
1769-- I am a comment
1770
1771str = --[[
1772This is a multi-line comment.
1773It's OK.
1774]] strA \ -- comment 1
1775 .. strB \ -- comment 2
1776 .. strC
1777
1778func --[[port]] 3000, --[[ip]] "192.168.1.1"
1779```
1780
1781</YueDisplay>
1782
1783## Try
1784
1785The syntax for Lua error handling in a common form.
1786
1787```yuescript
1788try
1789 func 1, 2, 3
1790catch err
1791 print yue.traceback err
1792
1793success, result = try
1794 func 1, 2, 3
1795catch err
1796 yue.traceback err
1797
1798try func 1, 2, 3
1799catch err
1800 print yue.traceback err
1801
1802success, result = try func 1, 2, 3
1803
1804try
1805 print "trying"
1806 func 1, 2, 3
1807
1808-- working with if assignment pattern
1809if success, result := try func 1, 2, 3
1810catch err
1811 print yue.traceback err
1812 print result
1813```
1814<YueDisplay>
1815
1816```yue
1817try
1818 func 1, 2, 3
1819catch err
1820 print yue.traceback err
1821
1822success, result = try
1823 func 1, 2, 3
1824catch err
1825 yue.traceback err
1826
1827try func 1, 2, 3
1828catch err
1829 print yue.traceback err
1830
1831success, result = try func 1, 2, 3
1832
1833try
1834 print "trying"
1835 func 1, 2, 3
1836
1837-- working with if assignment pattern
1838if success, result := try func 1, 2, 3
1839catch err
1840 print yue.traceback err
1841 print result
1842```
1843
1844</YueDisplay>
1845
1846### Try?
1847
1848`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.
1849
1850```yuescript
1851a, b, c = try? func!
1852
1853-- with nil coalescing operator
1854a = (try? func!) ?? "default"
1855
1856-- as function argument
1857f try? func!
1858
1859-- with catch block
1860f try?
1861 print 123
1862 func!
1863catch e
1864 print e
1865 e
1866```
1867<YueDisplay>
1868
1869```yue
1870a, b, c = try? func!
1871
1872-- with nil coalescing operator
1873a = (try? func!) ?? "default"
1874
1875-- as function argument
1876f try? func!
1877
1878-- with catch block
1879f try?
1880 print 123
1881 func!
1882catch e
1883 print e
1884 e
1885```
1886
1887</YueDisplay>
1888
1889## Attributes
1890
1891Syntax 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.
1892
1893```yuescript
1894const a = 123
1895close _ = <close>: -> print "Out of scope."
1896```
1897<YueDisplay>
1898
1899```yue
1900const a = 123
1901close _ = <close>: -> print "Out of scope."
1902```
1903
1904</YueDisplay>
1905
1906You can do desctructuring with variables attributed as constant.
1907
1908```yuescript
1909const {:a, :b, c, d} = tb
1910-- a = 1
1911```
1912<YueDisplay>
1913
1914```yue
1915const {:a, :b, c, d} = tb
1916-- a = 1
1917```
1918
1919</YueDisplay>
1920
1921You can also declare a global variable to be `const`.
1922
1923```yuescript
1924global const Constant = 123
1925-- Constant = 1
1926```
1927<YueDisplay>
1928
1929```yue
1930global const Constant = 123
1931-- Constant = 1
1932```
1933
1934</YueDisplay>
1935
1936## Literals
1937
1938All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**.
1939
1940Unlike Lua, Line breaks are allowed inside of single and double quote strings without an escape sequence:
1941
1942```yuescript
1943some_string = "Here is a string
1944 that has a line break in it."
1945
1946-- You can mix expressions into string literals using #{} syntax.
1947-- String interpolation is only available in double quoted strings.
1948print "I am #{math.random! * 100}% sure."
1949```
1950<YueDisplay>
1951
1952```yue
1953some_string = "Here is a string
1954 that has a line break in it."
1955
1956-- You can mix expressions into string literals using #{} syntax.
1957-- String interpolation is only available in double quoted strings.
1958print "I am #{math.random! * 100}% sure."
1959```
1960
1961</YueDisplay>
1962
1963### Number Literals
1964
1965You can use underscores in a number literal to increase readability.
1966
1967```yuescript
1968integer = 1_000_000
1969hex = 0xEF_BB_BF
1970binary = 0B10011
1971```
1972<YueDisplay>
1973
1974```yue
1975integer = 1_000_000
1976hex = 0xEF_BB_BF
1977binary = 0B10011
1978```
1979
1980</YueDisplay>
1981
1982### YAML Multiline String
1983
1984The `|` prefix introduces a YAML-style multiline string literal:
1985
1986```yuescript
1987str = |
1988 key: value
1989 list:
1990 - item1
1991 - #{expr}
1992```
1993<YueDisplay>
1994
1995```yue
1996str = |
1997 key: value
1998 list:
1999 - item1
2000 - #{expr}
2001```
2002
2003</YueDisplay>
2004
2005This 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)`.
2006
2007YAML 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.
2008
2009```yuescript
2010fn = ->
2011 str = |
2012 foo:
2013 bar: baz
2014 return str
2015```
2016<YueDisplay>
2017
2018```yue
2019fn = ->
2020 str = |
2021 foo:
2022 bar: baz
2023 return str
2024```
2025
2026</YueDisplay>
2027
2028Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures.
2029
2030All 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.
2031
2032```yuescript
2033str = |
2034 path: "C:\Program Files\App"
2035 note: 'He said: "#{Hello}!"'
2036```
2037<YueDisplay>
2038
2039```yue
2040str = |
2041 path: "C:\Program Files\App"
2042 note: 'He said: "#{Hello}!"'
2043```
2044
2045</YueDisplay>
2046
2047## Function Literals
2048
2049All functions are created using a function expression. A simple function is denoted using the arrow: **->**.
2050
2051```yuescript
2052my_function = ->
2053my_function() -- call the empty function
2054```
2055<YueDisplay>
2056
2057```yue
2058my_function = ->
2059my_function() -- call the empty function
2060```
2061
2062</YueDisplay>
2063
2064The body of the function can either be one statement placed directly after the arrow, or it can be a series of statements indented on the following lines:
2065
2066```yuescript
2067func_a = -> print "hello world"
2068
2069func_b = ->
2070 value = 100
2071 print "The value:", value
2072```
2073<YueDisplay>
2074
2075```yue
2076func_a = -> print "hello world"
2077
2078func_b = ->
2079 value = 100
2080 print "The value:", value
2081```
2082
2083</YueDisplay>
2084
2085If a function has no arguments, it can be called using the ! operator, instead of empty parentheses. The ! invocation is the preferred way to call functions with no arguments.
2086
2087```yuescript
2088func_a!
2089func_b()
2090```
2091<YueDisplay>
2092
2093```yue
2094func_a!
2095func_b()
2096```
2097
2098</YueDisplay>
2099
2100Functions with arguments can be created by preceding the arrow with a list of argument names in parentheses:
2101
2102```yuescript
2103sum = (x, y) -> print "sum", x + y
2104```
2105<YueDisplay>
2106
2107```yue
2108sum = (x, y) -> print "sum", x + y
2109```
2110
2111</YueDisplay>
2112
2113Functions can be called by listing the arguments after the name of an expression that evaluates to a function. When chaining together function calls, the arguments are applied to the closest function to the left.
2114
2115```yuescript
2116sum 10, 20
2117print sum 10, 20
2118
2119a b c "a", "b", "c"
2120```
2121<YueDisplay>
2122
2123```yue
2124sum 10, 20
2125print sum 10, 20
2126
2127a b c "a", "b", "c"
2128```
2129
2130</YueDisplay>
2131
2132In order to avoid ambiguity in when calling functions, parentheses can also be used to surround the arguments. This is required here in order to make sure the right arguments get sent to the right functions.
2133
2134```yuescript
2135print "x:", sum(10, 20), "y:", sum(30, 40)
2136```
2137<YueDisplay>
2138
2139```yue
2140print "x:", sum(10, 20), "y:", sum(30, 40)
2141```
2142
2143</YueDisplay>
2144
2145There must not be any space between the opening parenthesis and the function.
2146
2147Functions will coerce the last statement in their body into a return statement, this is called implicit return:
2148
2149```yuescript
2150sum = (x, y) -> x + y
2151print "The sum is ", sum 10, 20
2152```
2153<YueDisplay>
2154
2155```yue
2156sum = (x, y) -> x + y
2157print "The sum is ", sum 10, 20
2158```
2159
2160</YueDisplay>
2161
2162And if you need to explicitly return, you can use the return keyword:
2163
2164```yuescript
2165sum = (x, y) -> return x + y
2166```
2167<YueDisplay>
2168
2169```yue
2170sum = (x, y) -> return x + y
2171```
2172
2173</YueDisplay>
2174
2175Just like in Lua, functions can return multiple values. The last statement must be a list of values separated by commas:
2176
2177```yuescript
2178mystery = (x, y) -> x + y, x - y
2179a, b = mystery 10, 20
2180```
2181<YueDisplay>
2182
2183```yue
2184mystery = (x, y) -> x + y, x - y
2185a, b = mystery 10, 20
2186```
2187
2188</YueDisplay>
2189
2190### Fat Arrows
2191
2192Because it is an idiom in Lua to send an object as the first argument when calling a method, a special syntax is provided for creating functions which automatically includes a self argument.
2193
2194```yuescript
2195func = (num) => @value + num
2196```
2197<YueDisplay>
2198
2199```yue
2200func = (num) => @value + num
2201```
2202
2203</YueDisplay>
2204
2205### Argument Defaults
2206
2207It is possible to provide default values for the arguments of a function. An argument is determined to be empty if its value is nil. Any nil arguments that have a default value will be replace before the body of the function is run.
2208
2209```yuescript
2210my_function = (name = "something", height = 100) ->
2211 print "Hello I am", name
2212 print "My height is", height
2213```
2214<YueDisplay>
2215
2216```yue
2217my_function = (name = "something", height = 100) ->
2218 print "Hello I am", name
2219 print "My height is", height
2220```
2221
2222</YueDisplay>
2223
2224An argument default value expression is evaluated in the body of the function in the order of the argument declarations. For this reason default values have access to previously declared arguments.
2225
2226```yuescript
2227some_args = (x = 100, y = x + 1000) ->
2228 print x + y
2229```
2230<YueDisplay>
2231
2232```yue
2233some_args = (x = 100, y = x + 1000) ->
2234 print x + y
2235```
2236
2237</YueDisplay>
2238
2239### Considerations
2240
2241Because of the expressive parentheses-less way of calling functions, some restrictions must be put in place to avoid parsing ambiguity involving whitespace.
2242
2243The minus sign plays two roles, a unary negation operator and a binary subtraction operator. Consider how the following examples compile:
2244
2245```yuescript
2246a = x - 10
2247b = x-10
2248c = x -y
2249d = x- z
2250```
2251<YueDisplay>
2252
2253```yue
2254a = x - 10
2255b = x-10
2256c = x -y
2257d = x- z
2258```
2259
2260</YueDisplay>
2261
2262The precedence of the first argument of a function call can be controlled using whitespace if the argument is a literal string. In Lua, it is common to leave off parentheses when calling a function with a single string or table literal.
2263
2264When there is no space between a variable and a string literal, the function call takes precedence over any following expressions. No other arguments can be passed to the function when it is called this way.
2265
2266Where there is a space following a variable and a string literal, the function call acts as show above. The string literal belongs to any following expressions (if they exist), which serves as the argument list.
2267
2268```yuescript
2269x = func"hello" + 100
2270y = func "hello" + 100
2271```
2272<YueDisplay>
2273
2274```yue
2275x = func"hello" + 100
2276y = func "hello" + 100
2277```
2278
2279</YueDisplay>
2280
2281### Multi-line arguments
2282
2283When calling functions that take a large number of arguments, it is convenient to split the argument list over multiple lines. Because of the white-space sensitive nature of the language, care must be taken when splitting up the argument list.
2284
2285If an argument list is to be continued onto the next line, the current line must end in a comma. And the following line must be indented more than the current indentation. Once indented, all other argument lines must be at the same level of indentation to be part of the argument list
2286
2287```yuescript
2288my_func 5, 4, 3,
2289 8, 9, 10
2290
2291cool_func 1, 2,
2292 3, 4,
2293 5, 6,
2294 7, 8
2295```
2296<YueDisplay>
2297
2298```yue
2299my_func 5, 4, 3,
2300 8, 9, 10
2301
2302cool_func 1, 2,
2303 3, 4,
2304 5, 6,
2305 7, 8
2306```
2307
2308</YueDisplay>
2309
2310This type of invocation can be nested. The level of indentation is used to determine to which function the arguments belong to.
2311
2312```yuescript
2313my_func 5, 6, 7,
2314 6, another_func 6, 7, 8,
2315 9, 1, 2,
2316 5, 4
2317```
2318<YueDisplay>
2319
2320```yue
2321my_func 5, 6, 7,
2322 6, another_func 6, 7, 8,
2323 9, 1, 2,
2324 5, 4
2325```
2326
2327</YueDisplay>
2328
2329Because tables also use the comma as a delimiter, this indentation syntax is helpful for letting values be part of the argument list instead of being part of the table.
2330
2331```yuescript
2332x = [
2333 1, 2, 3, 4, a_func 4, 5,
2334 5, 6,
2335 8, 9, 10
2336]
2337```
2338<YueDisplay>
2339
2340```yue
2341x = [
2342 1, 2, 3, 4, a_func 4, 5,
2343 5, 6,
2344 8, 9, 10
2345]
2346```
2347
2348</YueDisplay>
2349
2350Although uncommon, notice how we can give a deeper indentation for function arguments if we know we will be using a lower indentation further on.
2351
2352```yuescript
2353y = [ my_func 1, 2, 3,
2354 4, 5,
2355 5, 6, 7
2356]
2357```
2358<YueDisplay>
2359
2360```yue
2361y = [ my_func 1, 2, 3,
2362 4, 5,
2363 5, 6, 7
2364]
2365```
2366
2367</YueDisplay>
2368
2369The same thing can be done with other block level statements like conditionals. We can use indentation level to determine what statement a value belongs to:
2370
2371```yuescript
2372if func 1, 2, 3,
2373 "hello",
2374 "world"
2375 print "hello"
2376 print "I am inside if"
2377
2378if func 1, 2, 3,
2379 "hello",
2380 "world"
2381 print "hello"
2382 print "I am inside if"
2383```
2384<YueDisplay>
2385
2386```yue
2387if func 1, 2, 3,
2388 "hello",
2389 "world"
2390 print "hello"
2391 print "I am inside if"
2392
2393if func 1, 2, 3,
2394 "hello",
2395 "world"
2396 print "hello"
2397 print "I am inside if"
2398```
2399
2400</YueDisplay>
2401
2402### Parameter Destructuring
2403
2404YueScript now supports destructuring function parameters when the argument is an object. Two forms of destructuring table literals are available:
2405
2406* **Curly-brace wrapped literals/object parameters**, allowing optional default values when fields are missing (e.g., `{:a, :b}`, `{a: a1 = 123}`).
2407
2408* **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.
2409
2410```yuescript
2411f1 = (:a, :b, :c) ->
2412 print a, b, c
2413
2414f1 a: 1, b: "2", c: {}
2415
2416f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2417 print a1, b, c
2418
2419arg1 = {a: 0}
2420f2 arg1, arg2
2421```
2422<YueDisplay>
2423
2424```yue
2425f1 = (:a, :b, :c) ->
2426 print a, b, c
2427
2428f1 a: 1, b: "2", c: {}
2429
2430f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2431print a1, b, c
2432
2433arg1 = {a: 0}
2434f2 arg1, arg2
2435```
2436
2437</YueDisplay>
2438
2439### Prefixed Return Expression
2440
2441When 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:
2442
2443```yuescript
2444findFirstEven = (list): nil ->
2445 for item in *list
2446 if type(item) == "table"
2447 for sub in *item
2448 if sub % 2 == 0
2449 return sub
2450```
2451<YueDisplay>
2452
2453```yue
2454findFirstEven = (list): nil ->
2455 for item in *list
2456 if type(item) == "table"
2457 for sub in *item
2458 if sub % 2 == 0
2459 return sub
2460```
2461
2462</YueDisplay>
2463
2464This is equivalent to:
2465
2466```yuescript
2467findFirstEven = (list) ->
2468 for item in *list
2469 if type(item) == "table"
2470 for sub in *item
2471 if sub % 2 == 0
2472 return sub
2473 nil
2474```
2475<YueDisplay>
2476
2477```yue
2478findFirstEven = (list) ->
2479 for item in *list
2480 if type(item) == "table"
2481 for sub in *item
2482 if sub % 2 == 0
2483 return sub
2484 nil
2485```
2486
2487</YueDisplay>
2488
2489The 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.
2490
2491### Named Varargs
2492
2493You can use the `(...t) ->` syntax to automatically store varargs into a named table. This table will contain all passed arguments (including `nil` values), and the `n` field of the table will store the actual number of arguments passed (including `nil` values).
2494
2495```yuescript
2496f = (...t) ->
2497 print "argument count:", t.n
2498 print "table length:", #t
2499 for i = 1, t.n
2500 print t[i]
2501
2502f 1, 2, 3
2503f "a", "b", "c", "d"
2504f!
2505
2506-- Handling cases with nil values
2507process = (...args) ->
2508 sum = 0
2509 for i = 1, args.n
2510 if args[i] != nil and type(args[i]) == "number"
2511 sum += args[i]
2512 sum
2513
2514process 1, nil, 3, nil, 5
2515```
2516<YueDisplay>
2517
2518```yue
2519f = (...t) ->
2520 print "argument count:", t.n
2521 print "table length:", #t
2522 for i = 1, t.n
2523 print t[i]
2524
2525f 1, 2, 3
2526f "a", "b", "c", "d"
2527f!
2528
2529-- Handling cases with nil values
2530process = (...args) ->
2531 sum = 0
2532 for i = 1, args.n
2533 if args[i] != nil and type(args[i]) == "number"
2534 sum += args[i]
2535 sum
2536
2537process 1, nil, 3, nil, 5
2538```
2539
2540</YueDisplay>
2541
2542## Backcalls
2543
2544Backcalls 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.
2545
2546```yuescript
2547<- f
2548print "hello"
2549```
2550<YueDisplay>
2551
2552```yue
2553<- f
2554print "hello"
2555```
2556
2557</YueDisplay>
2558
2559Fat arrow functions are also available.
2560
2561```yuescript
2562<= f
2563print @value
2564```
2565<YueDisplay>
2566
2567```yue
2568<= f
2569print @value
2570```
2571
2572</YueDisplay>
2573
2574You can specify a placeholder for where you want the backcall function to go as a parameter.
2575
2576```yuescript
2577(x) <- map _, [1, 2, 3]
2578x * 2
2579```
2580<YueDisplay>
2581
2582```yue
2583(x) <- map _, [1, 2, 3]
2584x * 2
2585```
2586
2587</YueDisplay>
2588
2589If 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.
2590
2591```yuescript
2592result, msg = do
2593 data <- readAsync "filename.txt"
2594 print data
2595 info <- processAsync data
2596 check info
2597print result, msg
2598```
2599<YueDisplay>
2600
2601```yue
2602result, msg = do
2603 data <- readAsync "filename.txt"
2604 print data
2605 info <- processAsync data
2606 check info
2607print result, msg
2608```
2609
2610</YueDisplay>
2611
2612## Table Literals
2613
2614Like in Lua, tables are delimited in curly braces.
2615
2616```yuescript
2617some_values = [1, 2, 3, 4]
2618```
2619<YueDisplay>
2620
2621```yue
2622some_values = [1, 2, 3, 4]
2623```
2624
2625</YueDisplay>
2626
2627Unlike Lua, assigning a value to a key in a table is done with **:** (instead of **=**).
2628
2629```yuescript
2630some_values = {
2631 name: "Bill",
2632 age: 200,
2633 ["favorite food"]: "rice"
2634}
2635```
2636<YueDisplay>
2637
2638```yue
2639some_values = {
2640 name: "Bill",
2641 age: 200,
2642 ["favorite food"]: "rice"
2643}
2644```
2645
2646</YueDisplay>
2647
2648The curly braces can be left off if a single table of key value pairs is being assigned.
2649
2650```yuescript
2651profile =
2652 height: "4 feet",
2653 shoe_size: 13,
2654 favorite_foods: ["ice cream", "donuts"]
2655```
2656<YueDisplay>
2657
2658```yue
2659profile =
2660 height: "4 feet",
2661 shoe_size: 13,
2662 favorite_foods: ["ice cream", "donuts"]
2663```
2664
2665</YueDisplay>
2666
2667Newlines can be used to delimit values instead of a comma (or both):
2668
2669```yuescript
2670values = {
2671 1, 2, 3, 4
2672 5, 6, 7, 8
2673 name: "superman"
2674 occupation: "crime fighting"
2675}
2676```
2677<YueDisplay>
2678
2679```yue
2680values = {
2681 1, 2, 3, 4
2682 5, 6, 7, 8
2683 name: "superman"
2684 occupation: "crime fighting"
2685}
2686```
2687
2688</YueDisplay>
2689
2690When creating a single line table literal, the curly braces can also be left off:
2691
2692```yuescript
2693my_function dance: "Tango", partner: "none"
2694
2695y = type: "dog", legs: 4, tails: 1
2696```
2697<YueDisplay>
2698
2699```yue
2700my_function dance: "Tango", partner: "none"
2701
2702y = type: "dog", legs: 4, tails: 1
2703```
2704
2705</YueDisplay>
2706
2707The keys of a table literal can be language keywords without being escaped:
2708
2709```yuescript
2710tbl = {
2711 do: "something"
2712 end: "hunger"
2713}
2714```
2715<YueDisplay>
2716
2717```yue
2718tbl = {
2719 do: "something"
2720 end: "hunger"
2721}
2722```
2723
2724</YueDisplay>
2725
2726If you are constructing a table out of variables and wish the keys to be the same as the variable names, then the **:** prefix operator can be used:
2727
2728```yuescript
2729hair = "golden"
2730height = 200
2731person = { :hair, :height, shoe_size: 40 }
2732
2733print_table :hair, :height
2734```
2735<YueDisplay>
2736
2737```yue
2738hair = "golden"
2739height = 200
2740person = { :hair, :height, shoe_size: 40 }
2741
2742print_table :hair, :height
2743```
2744
2745</YueDisplay>
2746
2747If you want the key of a field in the table to to be result of an expression, then you can wrap it in **[ ]**, just like in Lua. You can also use a string literal directly as a key, leaving out the square brackets. This is useful if your key has any special characters.
2748
2749```yuescript
2750t = {
2751 [1 + 2]: "hello"
2752 "hello world": true
2753}
2754```
2755<YueDisplay>
2756
2757```yue
2758t = {
2759 [1 + 2]: "hello"
2760 "hello world": true
2761}
2762```
2763
2764</YueDisplay>
2765
2766Lua tables have both an array part and a hash part, but sometimes you want to make a semantic distinction between array and hash usage when writing Lua tables. Then you can write Lua table with **[ ]** instead of **{ }** to represent an array table and writing any key value pair in a list table won't be allowed.
2767
2768```yuescript
2769some_values = [1, 2, 3, 4]
2770list_with_one_element = [1, ]
2771```
2772<YueDisplay>
2773
2774```yue
2775some_values = [1, 2, 3, 4]
2776list_with_one_element = [1, ]
2777```
2778
2779</YueDisplay>
2780
2781## Comprehensions
2782
2783Comprehensions provide a convenient syntax for constructing a new table by iterating over some existing object and applying an expression to its values. There are two kinds of comprehensions: list comprehensions and table comprehensions. They both produce Lua tables; list comprehensions accumulate values into an array-like table, and table comprehensions let you set both the key and the value on each iteration.
2784
2785### List Comprehensions
2786
2787The following creates a copy of the items table but with all the values doubled.
2788
2789```yuescript
2790items = [ 1, 2, 3, 4 ]
2791doubled = [item * 2 for i, item in ipairs items]
2792```
2793<YueDisplay>
2794
2795```yue
2796items = [ 1, 2, 3, 4 ]
2797doubled = [item * 2 for i, item in ipairs items]
2798```
2799
2800</YueDisplay>
2801
2802The items included in the new table can be restricted with a when clause:
2803
2804```yuescript
2805slice = [item for i, item in ipairs items when i > 1 and i < 3]
2806```
2807<YueDisplay>
2808
2809```yue
2810slice = [item for i, item in ipairs items when i > 1 and i < 3]
2811```
2812
2813</YueDisplay>
2814
2815Because it is common to iterate over the values of a numerically indexed table, an **\*** operator is introduced. The doubled example can be rewritten as:
2816
2817```yuescript
2818doubled = [item * 2 for item in *items]
2819```
2820<YueDisplay>
2821
2822```yue
2823doubled = [item * 2 for item in *items]
2824```
2825
2826</YueDisplay>
2827
2828In list comprehensions, you can also use the spread operator `...` to flatten nested lists, achieving a flat map effect:
2829
2830```yuescript
2831data =
2832 a: [1, 2, 3]
2833 b: [4, 5, 6]
2834
2835flat = [...v for k,v in pairs data]
2836-- flat is now [1, 2, 3, 4, 5, 6]
2837```
2838<YueDisplay>
2839
2840```yue
2841data =
2842 a: [1, 2, 3]
2843 b: [4, 5, 6]
2844
2845flat = [...v for k,v in pairs data]
2846-- flat is now [1, 2, 3, 4, 5, 6]
2847```
2848
2849</YueDisplay>
2850
2851The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause.
2852
2853Using multiple for clauses is the same as using nested loops:
2854
2855```yuescript
2856x_coords = [4, 5, 6, 7]
2857y_coords = [9, 2, 3]
2858
2859points = [ [x, y] for x in *x_coords \
2860for y in *y_coords]
2861```
2862<YueDisplay>
2863
2864```yue
2865x_coords = [4, 5, 6, 7]
2866y_coords = [9, 2, 3]
2867
2868points = [ [x, y] for x in *x_coords \
2869for y in *y_coords]
2870```
2871
2872</YueDisplay>
2873
2874Numeric for loops can also be used in comprehensions:
2875
2876```yuescript
2877evens = [i for i = 1, 100 when i % 2 == 0]
2878```
2879<YueDisplay>
2880
2881```yue
2882evens = [i for i = 1, 100 when i % 2 == 0]
2883```
2884
2885</YueDisplay>
2886
2887### Table Comprehensions
2888
2889The syntax for table comprehensions is very similar, only differing by using **{** and **}** and taking two values from each iteration.
2890
2891This example makes a copy of the tablething:
2892
2893```yuescript
2894thing = {
2895 color: "red"
2896 name: "fast"
2897 width: 123
2898}
2899
2900thing_copy = {k, v for k, v in pairs thing}
2901```
2902<YueDisplay>
2903
2904```yue
2905thing = {
2906 color: "red"
2907 name: "fast"
2908 width: 123
2909}
2910
2911thing_copy = {k, v for k, v in pairs thing}
2912```
2913
2914</YueDisplay>
2915
2916```yuescript
2917no_color = {k, v for k, v in pairs thing when k != "color"}
2918```
2919<YueDisplay>
2920
2921```yue
2922no_color = {k, v for k, v in pairs thing when k != "color"}
2923```
2924
2925</YueDisplay>
2926
2927The **\*** operator is also supported. Here we create a square root look up table for a few numbers.
2928
2929```yuescript
2930numbers = [1, 2, 3, 4]
2931sqrts = {i, math.sqrt i for i in *numbers}
2932```
2933<YueDisplay>
2934
2935```yue
2936numbers = [1, 2, 3, 4]
2937sqrts = {i, math.sqrt i for i in *numbers}
2938```
2939
2940</YueDisplay>
2941
2942The key-value tuple in a table comprehension can also come from a single expression, in which case the expression should return two values. The first is used as the key and the second is used as the value:
2943
2944In this example we convert an array of pairs to a table where the first item in the pair is the key and the second is the value.
2945
2946```yuescript
2947tuples = [ ["hello", "world"], ["foo", "bar"]]
2948tbl = {unpack tuple for tuple in *tuples}
2949```
2950<YueDisplay>
2951
2952```yue
2953tuples = [ ["hello", "world"], ["foo", "bar"]]
2954tbl = {unpack tuple for tuple in *tuples}
2955```
2956
2957</YueDisplay>
2958
2959### Slicing
2960
2961A special syntax is provided to restrict the items that are iterated over when using the **\*** operator. This is equivalent to setting the iteration bounds and a step size in a for loop.
2962
2963Here we can set the minimum and maximum bounds, taking all items with indexes between 1 and 5 inclusive:
2964
2965```yuescript
2966slice = [item for item in *items[1, 5]]
2967```
2968<YueDisplay>
2969
2970```yue
2971slice = [item for item in *items[1, 5]]
2972```
2973
2974</YueDisplay>
2975
2976Any of the slice arguments can be left off to use a sensible default. In this example, if the max index is left off it defaults to the length of the table. This will take everything but the first element:
2977
2978```yuescript
2979slice = [item for item in *items[2,]]
2980```
2981<YueDisplay>
2982
2983```yue
2984slice = [item for item in *items[2,]]
2985```
2986
2987</YueDisplay>
2988
2989If the minimum bound is left out, it defaults to 1. Here we only provide a step size and leave the other bounds blank. This takes all odd indexed items: (1, 3, 5, …)
2990
2991```yuescript
2992slice = [item for item in *items[,,2]]
2993```
2994<YueDisplay>
2995
2996```yue
2997slice = [item for item in *items[,,2]]
2998```
2999
3000</YueDisplay>
3001
3002Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table.
3003
3004```yuescript
3005-- take the last 4 items
3006slice = [item for item in *items[-4,-1]]
3007```
3008<YueDisplay>
3009
3010```yue
3011-- take the last 4 items
3012slice = [item for item in *items[-4,-1]]
3013```
3014
3015</YueDisplay>
3016
3017The step size can also be negative, which means that the items are taken in reverse order.
3018
3019```yuescript
3020reverse_slice = [item for item in *items[-1,1,-1]]
3021```
3022<YueDisplay>
3023
3024```yue
3025reverse_slice = [item for item in *items[-1,1,-1]]
3026```
3027
3028</YueDisplay>
3029
3030#### Slicing Expression
3031
3032Slicing can also be used as an expression. This is useful for getting a sub-list of a table.
3033
3034```yuescript
3035-- take the 2nd and 4th items as a new list
3036sub_list = items[2, 4]
3037```
3038<YueDisplay>
3039
3040```yue
3041-- take the 2nd and 4th items as a new list
3042sub_list = items[2, 4]
3043```
3044
3045</YueDisplay>
3046
3047## For Loop
3048
3049There are two for loop forms, just like in Lua. A numeric one and a generic one:
3050
3051```yuescript
3052for i = 10, 20
3053 print i
3054
3055for k = 1, 15, 2 -- an optional step provided
3056 print k
3057
3058for key, value in pairs object
3059 print key, value
3060```
3061<YueDisplay>
3062
3063```yue
3064for i = 10, 20
3065 print i
3066
3067for k = 1, 15, 2 -- an optional step provided
3068 print k
3069
3070for key, value in pairs object
3071 print key, value
3072```
3073
3074</YueDisplay>
3075
3076The slicing and **\*** operators can be used, just like with comprehensions:
3077
3078```yuescript
3079for item in *items[2, 4]
3080 print item
3081```
3082<YueDisplay>
3083
3084```yue
3085for item in *items[2, 4]
3086 print item
3087```
3088
3089</YueDisplay>
3090
3091A shorter syntax is also available for all variations when the body is only a single line:
3092
3093```yuescript
3094for item in *items do print item
3095
3096for j = 1, 10, 3 do print j
3097```
3098<YueDisplay>
3099
3100```yue
3101for item in *items do print item
3102
3103for j = 1, 10, 3 do print j
3104```
3105
3106</YueDisplay>
3107
3108A for loop can also be used as an expression. The last statement in the body of the for loop is coerced into an expression and appended to an accumulating array table.
3109
3110Doubling every even number:
3111
3112```yuescript
3113doubled_evens = for i = 1, 20
3114 if i % 2 == 0
3115 i * 2
3116 else
3117 i
3118```
3119<YueDisplay>
3120
3121```yue
3122doubled_evens = for i = 1, 20
3123 if i % 2 == 0
3124 i * 2
3125 else
3126 i
3127```
3128
3129</YueDisplay>
3130
3131In 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.
3132
3133For example, to find the first number greater than 10:
3134
3135```yuescript
3136first_large = for n in *numbers
3137 break n if n > 10
3138```
3139<YueDisplay>
3140
3141```yue
3142first_large = for n in *numbers
3143 break n if n > 10
3144```
3145
3146</YueDisplay>
3147
3148This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions.
3149
3150You can also filter values by combining the for loop expression with the continue statement.
3151
3152For 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.
3153
3154```yuescript
3155func_a = -> for i = 1, 10 do print i
3156func_b = -> return for i = 1, 10 do i
3157
3158print func_a! -- prints nil
3159print func_b! -- prints table object
3160```
3161<YueDisplay>
3162
3163```yue
3164func_a = -> for i = 1, 10 do print i
3165func_b = -> return for i = 1, 10 do i
3166
3167print func_a! -- prints nil
3168print func_b! -- prints table object
3169```
3170
3171</YueDisplay>
3172
3173This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop.
3174
3175## Repeat Loop
3176
3177The repeat loop comes from Lua:
3178
3179```yuescript
3180i = 10
3181repeat
3182 print i
3183 i -= 1
3184until i == 0
3185```
3186<YueDisplay>
3187
3188```yue
3189i = 10
3190repeat
3191 print i
3192 i -= 1
3193until i == 0
3194```
3195
3196</YueDisplay>
3197
3198## While Loop
3199
3200The while loop also comes in four variations:
3201
3202```yuescript
3203i = 10
3204while i > 0
3205 print i
3206 i -= 1
3207
3208while running == true do my_function!
3209```
3210<YueDisplay>
3211
3212```yue
3213i = 10
3214while i > 0
3215 print i
3216 i -= 1
3217
3218while running == true do my_function!
3219```
3220
3221</YueDisplay>
3222
3223```yuescript
3224i = 10
3225until i == 0
3226 print i
3227 i -= 1
3228
3229until running == false do my_function!
3230```
3231<YueDisplay>
3232
3233```yue
3234i = 10
3235until i == 0
3236 print i
3237 i -= 1
3238until running == false do my_function!
3239```
3240
3241</YueDisplay>
3242
3243Like for loops, the while loop can also be used an expression. Additionally, for a function to return the accumulated value of a while loop, the statement must be explicitly returned.
3244
3245## Continue
3246
3247A continue statement can be used to skip the current iteration in a loop.
3248
3249```yuescript
3250i = 0
3251while i < 10
3252 i += 1
3253 continue if i % 2 == 0
3254 print i
3255```
3256<YueDisplay>
3257
3258```yue
3259i = 0
3260while i < 10
3261 i += 1
3262 continue if i % 2 == 0
3263 print i
3264```
3265
3266</YueDisplay>
3267
3268continue can also be used with loop expressions to prevent that iteration from accumulating into the result. This examples filters the array table into just even numbers:
3269
3270```yuescript
3271my_numbers = [1, 2, 3, 4, 5, 6]
3272odds = for x in *my_numbers
3273 continue if x % 2 == 1
3274 x
3275```
3276<YueDisplay>
3277
3278```yue
3279my_numbers = [1, 2, 3, 4, 5, 6]
3280odds = for x in *my_numbers
3281 continue if x % 2 == 1
3282 x
3283```
3284
3285</YueDisplay>
3286
3287## Conditionals
3288
3289```yuescript
3290have_coins = false
3291if have_coins
3292 print "Got coins"
3293else
3294 print "No coins"
3295```
3296<YueDisplay>
3297
3298```yue
3299have_coins = false
3300if have_coins
3301 print "Got coins"
3302else
3303 print "No coins"
3304```
3305
3306</YueDisplay>
3307
3308A short syntax for single statements can also be used:
3309
3310```yuescript
3311have_coins = false
3312if have_coins then print "Got coins" else print "No coins"
3313```
3314<YueDisplay>
3315
3316```yue
3317have_coins = false
3318if have_coins then print "Got coins" else print "No coins"
3319```
3320
3321</YueDisplay>
3322
3323Because if statements can be used as expressions, this can also be written as:
3324
3325```yuescript
3326have_coins = false
3327print if have_coins then "Got coins" else "No coins"
3328```
3329<YueDisplay>
3330
3331```yue
3332have_coins = false
3333print if have_coins then "Got coins" else "No coins"
3334```
3335
3336</YueDisplay>
3337
3338Conditionals can also be used in return statements and assignments:
3339
3340```yuescript
3341is_tall = (name) ->
3342 if name == "Rob"
3343 true
3344 else
3345 false
3346
3347message = if is_tall "Rob"
3348 "I am very tall"
3349else
3350 "I am not so tall"
3351
3352print message -- prints: I am very tall
3353```
3354<YueDisplay>
3355
3356```yue
3357is_tall = (name) ->
3358 if name == "Rob"
3359 true
3360 else
3361 false
3362
3363message = if is_tall "Rob"
3364 "I am very tall"
3365else
3366 "I am not so tall"
3367
3368print message -- prints: I am very tall
3369```
3370
3371</YueDisplay>
3372
3373The opposite of if is unless:
3374
3375```yuescript
3376unless os.date("%A") == "Monday"
3377 print "it is not Monday!"
3378```
3379<YueDisplay>
3380
3381```yue
3382unless os.date("%A") == "Monday"
3383 print "it is not Monday!"
3384```
3385
3386</YueDisplay>
3387
3388```yuescript
3389print "You're lucky!" unless math.random! > 0.1
3390```
3391<YueDisplay>
3392
3393```yue
3394print "You're lucky!" unless math.random! > 0.1
3395```
3396
3397</YueDisplay>
3398
3399### In Expression
3400
3401You can write range checking code with an `in-expression`.
3402
3403```yuescript
3404a = 5
3405
3406if a in [1, 3, 5, 7]
3407 print "checking equality with discrete values"
3408
3409if a in list
3410 print "checking if `a` is in a list"
3411```
3412<YueDisplay>
3413
3414```yue
3415a = 5
3416
3417if a in [1, 3, 5, 7]
3418 print "checking equality with discrete values"
3419
3420if a in list
3421 print "checking if `a` is in a list"
3422```
3423
3424</YueDisplay>
3425
3426```yuescript
3427print "You're lucky!" unless math.random! > 0.1
3428```
3429<YueDisplay>
3430
3431```yue
3432print "You're lucky!" unless math.random! > 0.1
3433```
3434
3435</YueDisplay>
3436
3437## Line Decorators
3438
3439For convenience, the for loop and if statement can be applied to single statements at the end of the line:
3440
3441```yuescript
3442print "hello world" if name == "Rob"
3443```
3444<YueDisplay>
3445
3446```yue
3447print "hello world" if name == "Rob"
3448```
3449
3450</YueDisplay>
3451
3452And with basic loops:
3453
3454```yuescript
3455print "item: ", item for item in *items
3456```
3457<YueDisplay>
3458
3459```yue
3460print "item: ", item for item in *items
3461```
3462
3463</YueDisplay>
3464
3465And with while loops:
3466
3467```yuescript
3468game\update! while game\isRunning!
3469
3470reader\parse_line! until reader\eof!
3471```
3472<YueDisplay>
3473
3474```yue
3475game\update! while game\isRunning!
3476
3477reader\parse_line! until reader\eof!
3478```
3479
3480</YueDisplay>
3481
3482## Switch
3483
3484The 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.
3485
3486```yuescript
3487switch name := "Dan"
3488 when "Robert"
3489 print "You are Robert"
3490 when "Dan", "Daniel"
3491 print "Your name, it's Dan"
3492 else
3493 print "I don't know about you with name #{name}"
3494```
3495<YueDisplay>
3496
3497```yue
3498switch name := "Dan"
3499 when "Robert"
3500 print "You are Robert"
3501 when "Dan", "Daniel"
3502 print "Your name, it's Dan"
3503 else
3504 print "I don't know about you with name #{name}"
3505```
3506
3507</YueDisplay>
3508
3509A switch when clause can match against multiple values by listing them out comma separated.
3510
3511Switches can be used as expressions as well, here we can assign the result of the switch to a variable:
3512
3513```yuescript
3514b = 1
3515next_number = switch b
3516 when 1
3517 2
3518 when 2
3519 3
3520 else
3521 error "can't count that high!"
3522```
3523<YueDisplay>
3524
3525```yue
3526b = 1
3527next_number = switch b
3528 when 1
3529 2
3530 when 2
3531 3
3532 else
3533 error "can't count that high!"
3534```
3535
3536</YueDisplay>
3537
3538We 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.
3539
3540```yuescript
3541msg = switch math.random(1, 5)
3542 when 1 then "you are lucky"
3543 when 2 then "you are almost lucky"
3544 else "not so lucky"
3545```
3546<YueDisplay>
3547
3548```yue
3549msg = switch math.random(1, 5)
3550 when 1 then "you are lucky"
3551 when 2 then "you are almost lucky"
3552 else "not so lucky"
3553```
3554
3555</YueDisplay>
3556
3557If you want to write code with one less indent when writing a switch statement, you can put the first when clause on the statement start line, and then all other clauses can be written with one less indent.
3558
3559```yuescript
3560switch math.random(1, 5)
3561 when 1
3562 print "you are lucky" -- two indents
3563 else
3564 print "not so lucky"
3565
3566switch math.random(1, 5) when 1
3567 print "you are lucky" -- one indent
3568else
3569 print "not so lucky"
3570```
3571<YueDisplay>
3572
3573```yue
3574switch math.random(1, 5)
3575 when 1
3576 print "you are lucky" -- two indents
3577 else
3578 print "not so lucky"
3579
3580switch math.random(1, 5) when 1
3581 print "you are lucky" -- one indent
3582else
3583 print "not so lucky"
3584```
3585
3586</YueDisplay>
3587
3588It 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.
3589
3590### Table Matching
3591
3592You can do table matching in a switch when clause, if the table can be destructured by a specific structure and get non-nil values.
3593
3594```yuescript
3595items =
3596 * x: 100
3597 y: 200
3598 * width: 300
3599 height: 400
3600
3601for item in *items
3602 switch item
3603 when :x, :y
3604 print "Vec2 #{x}, #{y}"
3605 when :width, :height
3606 print "size #{width}, #{height}"
3607```
3608<YueDisplay>
3609
3610```yue
3611items =
3612 * x: 100
3613 y: 200
3614 * width: 300
3615 height: 400
3616
3617for item in *items
3618 switch item
3619 when :x, :y
3620 print "Vec2 #{x}, #{y}"
3621 when :width, :height
3622 print "size #{width}, #{height}"
3623```
3624
3625</YueDisplay>
3626
3627You can use default values to optionally destructure the table for some fields.
3628
3629```yuescript
3630item = {}
3631
3632{pos: {:x = 50, :y = 200}} = item -- get error: attempt to index a nil value (field 'pos')
3633
3634switch item
3635 when {pos: {:x = 50, :y = 200}}
3636 print "Vec2 #{x}, #{y}" -- table destructuring will still pass
3637```
3638<YueDisplay>
3639
3640```yue
3641item = {}
3642
3643{pos: {:x = 50, :y = 200}} = item -- get error: attempt to index a nil value (field 'pos')
3644
3645switch item
3646 when {pos: {:x = 50, :y = 200}}
3647 print "Vec2 #{x}, #{y}" -- table destructuring will still pass
3648```
3649
3650</YueDisplay>
3651
3652You can also match against array elements, table fields, and even nested structures with array or table literals.
3653
3654Match against array elements.
3655
3656```yuescript
3657switch tb
3658 when [1, 2, 3]
3659 print "1, 2, 3"
3660 when [1, b, 3]
3661 print "1, #{b}, 3"
3662 when [1, 2, b = 3] -- b has a default value
3663 print "1, 2, #{b}"
3664```
3665<YueDisplay>
3666
3667```yue
3668switch tb
3669 when [1, 2, 3]
3670 print "1, 2, 3"
3671 when [1, b, 3]
3672 print "1, #{b}, 3"
3673 when [1, 2, b = 3] -- b has a default value
3674 print "1, 2, #{b}"
3675```
3676
3677</YueDisplay>
3678
3679Match against table fields with destructuring.
3680
3681```yuescript
3682switch tb
3683 when success: true, :result
3684 print "success", result
3685 when success: false
3686 print "failed", result
3687 else
3688 print "invalid"
3689```
3690<YueDisplay>
3691
3692```yue
3693switch tb
3694 when success: true, :result
3695 print "success", result
3696 when success: false
3697 print "failed", result
3698 else
3699 print "invalid"
3700```
3701
3702</YueDisplay>
3703
3704Match against nested table structures.
3705
3706```yuescript
3707switch tb
3708 when data: {type: "success", :content}
3709 print "success", content
3710 when data: {type: "error", :content}
3711 print "failed", content
3712 else
3713 print "invalid"
3714```
3715<YueDisplay>
3716
3717```yue
3718switch tb
3719 when data: {type: "success", :content}
3720 print "success", content
3721 when data: {type: "error", :content}
3722 print "failed", content
3723 else
3724 print "invalid"
3725```
3726
3727</YueDisplay>
3728
3729Match against array of tables.
3730
3731```yuescript
3732switch tb
3733 when [
3734 {a: 1, b: 2}
3735 {a: 3, b: 4}
3736 {a: 5, b: 6}
3737 fourth
3738 ]
3739 print "matched", fourth
3740```
3741<YueDisplay>
3742
3743```yue
3744switch tb
3745 when [
3746 {a: 1, b: 2}
3747 {a: 3, b: 4}
3748 {a: 5, b: 6}
3749 fourth
3750 ]
3751 print "matched", fourth
3752```
3753
3754</YueDisplay>
3755
3756Match against a list and capture a range of elements.
3757
3758```yuescript
3759segments = ["admin", "users", "logs", "view"]
3760switch segments
3761 when [...groups, resource, action]
3762 print "Group:", groups -- prints: {"admin", "users"}
3763 print "Resource:", resource -- prints: "logs"
3764 print "Action:", action -- prints: "view"
3765```
3766<YueDisplay>
3767
3768```yue
3769segments = ["admin", "users", "logs", "view"]
3770switch segments
3771 when [...groups, resource, action]
3772 print "Group:", groups -- prints: {"admin", "users"}
3773 print "Resource:", resource -- prints: "logs"
3774 print "Action:", action -- prints: "view"
3775```
3776
3777</YueDisplay>
3778
3779## Object Oriented Programming
3780
3781In 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.
3782
3783A simple class:
3784
3785```yuescript
3786class Inventory
3787 new: =>
3788 @items = {}
3789
3790 add_item: (name) =>
3791 if @items[name]
3792 @items[name] += 1
3793 else
3794 @items[name] = 1
3795```
3796<YueDisplay>
3797
3798```yue
3799class Inventory
3800 new: =>
3801 @items = {}
3802
3803 add_item: (name) =>
3804 if @items[name]
3805 @items[name] += 1
3806 else
3807 @items[name] = 1
3808```
3809
3810</YueDisplay>
3811
3812A class is declared with a class statement followed by a table-like declaration where all of the methods and properties are listed.
3813
3814The new property is special in that it will become the constructor.
3815
3816Notice how all the methods in the class use the fat arrow function syntax. When calling methods on a instance, the instance itself is sent in as the first argument. The fat arrow handles the creation of a self argument.
3817
3818The @ prefix on a variable name is shorthand for self.. @items becomes self.items.
3819
3820Creating an instance of the class is done by calling the name of the class as a function.
3821
3822```yuescript
3823inv = Inventory!
3824inv\add_item "t-shirt"
3825inv\add_item "pants"
3826```
3827<YueDisplay>
3828
3829```yue
3830inv = Inventory!
3831inv\add_item "t-shirt"
3832inv\add_item "pants"
3833```
3834
3835</YueDisplay>
3836
3837Because the instance of the class needs to be sent to the methods when they are called, the \ operator is used.
3838
3839All properties of a class are shared among the instances. This is fine for functions, but for other types of objects, undesired results may occur.
3840
3841Consider the example below, the clothes property is shared amongst all instances, so modifications to it in one instance will show up in another:
3842
3843```yuescript
3844class Person
3845 clothes: []
3846 give_item: (name) =>
3847 table.insert @clothes, name
3848
3849a = Person!
3850b = Person!
3851
3852a\give_item "pants"
3853b\give_item "shirt"
3854
3855-- will print both pants and shirt
3856print item for item in *a.clothes
3857```
3858<YueDisplay>
3859
3860```yue
3861class Person
3862 clothes: []
3863 give_item: (name) =>
3864 table.insert @clothes, name
3865
3866a = Person!
3867b = Person!
3868
3869a\give_item "pants"
3870b\give_item "shirt"
3871
3872-- will print both pants and shirt
3873print item for item in *a.clothes
3874```
3875
3876</YueDisplay>
3877
3878The proper way to avoid this problem is to create the mutable state of the object in the constructor:
3879
3880```yuescript
3881class Person
3882 new: =>
3883 @clothes = []
3884```
3885<YueDisplay>
3886
3887```yue
3888class Person
3889 new: =>
3890 @clothes = []
3891```
3892
3893</YueDisplay>
3894
3895### Inheritance
3896
3897The extends keyword can be used in a class declaration to inherit the properties and methods from another class.
3898
3899```yuescript
3900class BackPack extends Inventory
3901 size: 10
3902 add_item: (name) =>
3903 if #@items > size then error "backpack is full"
3904 super name
3905```
3906<YueDisplay>
3907
3908```yue
3909class BackPack extends Inventory
3910 size: 10
3911 add_item: (name) =>
3912 if #@items > size then error "backpack is full"
3913 super name
3914```
3915
3916</YueDisplay>
3917
3918Here we extend our Inventory class, and limit the amount of items it can carry.
3919
3920In 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.
3921
3922Whenever 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.
3923
3924```yuescript
3925class Shelf
3926 @__inherited: (child) =>
3927 print @__name, "was inherited by", child.__name
3928
3929-- will print: Shelf was inherited by Cupboard
3930class Cupboard extends Shelf
3931```
3932<YueDisplay>
3933
3934```yue
3935class Shelf
3936 @__inherited: (child) =>
3937 print @__name, "was inherited by", child.__name
3938
3939-- will print: Shelf was inherited by Cupboard
3940class Cupboard extends Shelf
3941```
3942
3943</YueDisplay>
3944
3945### Super
3946
3947**super** is a special keyword that can be used in two different ways: It can be treated as an object, or it can be called like a function. It only has special functionality when inside a class.
3948
3949When called as a function, it will call the function of the same name in the parent class. The current self will automatically be passed as the first argument. (As seen in the inheritance example above)
3950
3951When super is used as a normal value, it is a reference to the parent class object.
3952
3953It can be accessed like any of object in order to retrieve values in the parent class that might have been shadowed by the child class.
3954
3955When the \ calling operator is used with super, self is inserted as the first argument instead of the value of super itself. When using . to retrieve a function, the raw function is returned.
3956
3957A few examples of using super in different ways:
3958
3959```yuescript
3960class MyClass extends ParentClass
3961 a_method: =>
3962 -- the following have the same effect:
3963 super "hello", "world"
3964 super\a_method "hello", "world"
3965 super.a_method self, "hello", "world"
3966
3967 -- super as a value is equal to the parent class:
3968 assert super == ParentClass
3969```
3970<YueDisplay>
3971
3972```yue
3973class MyClass extends ParentClass
3974 a_method: =>
3975 -- the following have the same effect:
3976 super "hello", "world"
3977 super\a_method "hello", "world"
3978 super.a_method self, "hello", "world"
3979
3980 -- super as a value is equal to the parent class:
3981 assert super == ParentClass
3982```
3983
3984</YueDisplay>
3985
3986**super** can also be used on left side of a Function Stub. The only major difference is that instead of the resulting function being bound to the value of super, it is bound to self.
3987
3988### Types
3989
3990Every instance of a class carries its type with it. This is stored in the special __class property. This property holds the class object. The class object is what we call to build a new instance. We can also index the class object to retrieve class methods and properties.
3991
3992```yuescript
3993b = BackPack!
3994assert b.__class == BackPack
3995
3996print BackPack.size -- prints 10
3997```
3998<YueDisplay>
3999
4000```yue
4001b = BackPack!
4002assert b.__class == BackPack
4003
4004print BackPack.size -- prints 10
4005```
4006
4007</YueDisplay>
4008
4009### Class Objects
4010
4011The 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.
4012
4013The 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.
4014
4015A 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.
4016
4017The 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.
4018
4019It 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.
4020
4021The class object has a couple special properties:
4022
4023The name of the class as when it was declared is stored as a string in the __name field of the class object.
4024
4025```yuescript
4026print BackPack.__name -- prints Backpack
4027```
4028<YueDisplay>
4029
4030```yue
4031print BackPack.__name -- prints Backpack
4032```
4033
4034</YueDisplay>
4035
4036The base object is stored in __base. We can modify this table to add functionality to instances that have already been created and ones that are yet to be created.
4037
4038If the class extends from anything, the parent class object is stored in __parent.
4039
4040### Class Variables
4041
4042We can create variables directly in the class object instead of in the base by using @ in the front of the property name in a class declaration.
4043
4044```yuescript
4045class Things
4046 @some_func: => print "Hello from", @__name
4047
4048Things\some_func!
4049
4050-- class variables not visible in instances
4051assert Things().some_func == nil
4052```
4053<YueDisplay>
4054
4055```yue
4056class Things
4057 @some_func: => print "Hello from", @__name
4058
4059Things\some_func!
4060
4061-- class variables not visible in instances
4062assert Things().some_func == nil
4063```
4064
4065</YueDisplay>
4066
4067In expressions, we can use @@ to access a value that is stored in the __class of self. Thus, @@hello is shorthand for self.__class.hello.
4068
4069```yuescript
4070class Counter
4071 @count: 0
4072
4073 new: =>
4074 @@count += 1
4075
4076Counter!
4077Counter!
4078
4079print Counter.count -- prints 2
4080```
4081<YueDisplay>
4082
4083```yue
4084class Counter
4085 @count: 0
4086
4087 new: =>
4088 @@count += 1
4089
4090Counter!
4091Counter!
4092
4093print Counter.count -- prints 2
4094```
4095
4096</YueDisplay>
4097
4098The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax.
4099
4100```yuescript
4101@@hello 1,2,3,4
4102```
4103<YueDisplay>
4104
4105```yue
4106@@hello 1,2,3,4
4107```
4108
4109</YueDisplay>
4110
4111### Class Declaration Statements
4112
4113In 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.
4114
4115Here is an alternative way to create a class variable compared to what's described above:
4116
4117```yuescript
4118class Things
4119 @class_var = "hello world"
4120```
4121<YueDisplay>
4122
4123```yue
4124class Things
4125 @class_var = "hello world"
4126```
4127
4128</YueDisplay>
4129
4130These expressions are executed after all the properties have been added to the base.
4131
4132All variables declared in the body of the class are local to the classes properties. This is convenient for placing private values or helper functions that only the class methods can access:
4133
4134```yuescript
4135class MoreThings
4136 secret = 123
4137 log = (msg) -> print "LOG:", msg
4138
4139 some_method: =>
4140 log "hello world: " .. secret
4141```
4142<YueDisplay>
4143
4144```yue
4145class MoreThings
4146 secret = 123
4147 log = (msg) -> print "LOG:", msg
4148
4149 some_method: =>
4150 log "hello world: " .. secret
4151```
4152
4153</YueDisplay>
4154
4155### @ and @@ Values
4156
4157When @ and @@ are prefixed in front of a name they represent, respectively, that name accessed in self and self.__class.
4158
4159If they are used all by themselves, they are aliases for self and self.__class.
4160
4161```yuescript
4162assert @ == self
4163assert @@ == self.__class
4164```
4165<YueDisplay>
4166
4167```yue
4168assert @ == self
4169assert @@ == self.__class
4170```
4171
4172</YueDisplay>
4173
4174For example, a quick way to create a new instance of the same class from an instance method using @@:
4175
4176```yuescript
4177some_instance_method = (...) => @@ ...
4178```
4179<YueDisplay>
4180
4181```yue
4182some_instance_method = (...) => @@ ...
4183```
4184
4185</YueDisplay>
4186
4187### Constructor Property Promotion
4188
4189To reduce the boilerplate code for definition of simple value objects. You can write a simple class like:
4190
4191```yuescript
4192class Something
4193 new: (@foo, @bar, @@biz, @@baz) =>
4194
4195-- Which is short for
4196
4197class Something
4198 new: (foo, bar, biz, baz) =>
4199 @foo = foo
4200 @bar = bar
4201 @@biz = biz
4202 @@baz = baz
4203```
4204<YueDisplay>
4205
4206```yue
4207class Something
4208 new: (@foo, @bar, @@biz, @@baz) =>
4209
4210-- Which is short for
4211
4212class Something
4213 new: (foo, bar, biz, baz) =>
4214 @foo = foo
4215 @bar = bar
4216 @@biz = biz
4217 @@baz = baz
4218```
4219
4220</YueDisplay>
4221
4222You can also use this syntax for a common function to initialize a object's fields.
4223
4224```yuescript
4225new = (@fieldA, @fieldB) => @
4226obj = new {}, 123, "abc"
4227print obj
4228```
4229<YueDisplay>
4230
4231```yue
4232new = (@fieldA, @fieldB) => @
4233obj = new {}, 123, "abc"
4234print obj
4235```
4236
4237</YueDisplay>
4238
4239### Class Expressions
4240
4241The class syntax can also be used as an expression which can be assigned to a variable or explicitly returned.
4242
4243```yuescript
4244x = class Bucket
4245 drops: 0
4246 add_drop: => @drops += 1
4247```
4248<YueDisplay>
4249
4250```yue
4251x = class Bucket
4252 drops: 0
4253 add_drop: => @drops += 1
4254```
4255
4256</YueDisplay>
4257
4258### Anonymous classes
4259
4260The name can be left out when declaring a class. The __name attribute will be nil, unless the class expression is in an assignment. The name on the left hand side of the assignment is used instead of nil.
4261
4262```yuescript
4263BigBucket = class extends Bucket
4264 add_drop: => @drops += 10
4265
4266assert Bucket.__name == "BigBucket"
4267```
4268<YueDisplay>
4269
4270```yue
4271BigBucket = class extends Bucket
4272 add_drop: => @drops += 10
4273
4274assert Bucket.__name == "BigBucket"
4275```
4276
4277</YueDisplay>
4278
4279You can even leave off the body, meaning you can write a blank anonymous class like this:
4280
4281```yuescript
4282x = class
4283```
4284<YueDisplay>
4285
4286```yue
4287x = class
4288```
4289
4290</YueDisplay>
4291
4292### Class Mixing
4293
4294You can do mixing with keyword `using` to copy functions from either a plain table or a predefined class object into your new class. When doing mixing with a plain table, you can override the class indexing function (metamethod `__index`) to your customized implementation. When doing mixing with an existing class object, the class object's metamethods won't be copied.
4295
4296```yuescript
4297MyIndex = __index: var: 1
4298
4299class X using MyIndex
4300 func: =>
4301 print 123
4302
4303x = X!
4304print x.var
4305
4306class Y using X
4307
4308y = Y!
4309y\func!
4310
4311assert y.__class.__parent ~= X -- X is not parent of Y
4312```
4313<YueDisplay>
4314
4315```yue
4316MyIndex = __index: var: 1
4317
4318class X using MyIndex
4319 func: =>
4320 print 123
4321
4322x = X!
4323print x.var
4324
4325class Y using X
4326
4327y = Y!
4328y\func!
4329
4330assert y.__class.__parent ~= X -- X is not parent of Y
4331```
4332
4333</YueDisplay>
4334
4335## With Statement
4336
4337A common pattern involving the creation of an object is calling a series of functions and setting a series of properties immediately after creating it.
4338
4339This results in repeating the name of the object multiple times in code, adding unnecessary noise. A common solution to this is to pass a table in as an argument which contains a collection of keys and values to overwrite. The downside to this is that the constructor of this object must support this form.
4340
4341The with block helps to alleviate this. Within a with block we can use a special statements that begin with either . or \ which represent those operations applied to the object we are using with on.
4342
4343For example, we work with a newly created object:
4344
4345```yuescript
4346with Person!
4347 .name = "Oswald"
4348 \add_relative my_dad
4349 \save!
4350 print .name
4351```
4352<YueDisplay>
4353
4354```yue
4355with Person!
4356 .name = "Oswald"
4357 \add_relative my_dad
4358 \save!
4359 print .name
4360```
4361
4362</YueDisplay>
4363
4364The with statement can also be used as an expression which returns the value it has been giving access to.
4365
4366```yuescript
4367file = with File "favorite_foods.txt"
4368 \set_encoding "utf8"
4369```
4370<YueDisplay>
4371
4372```yue
4373file = with File "favorite_foods.txt"
4374 \set_encoding "utf8"
4375```
4376
4377</YueDisplay>
4378
4379Or…
4380
4381```yuescript
4382create_person = (name, relatives) ->
4383 with Person!
4384 .name = name
4385 \add_relative relative for relative in *relatives
4386
4387me = create_person "Leaf", [dad, mother, sister]
4388```
4389<YueDisplay>
4390
4391```yue
4392create_person = (name, relatives) ->
4393 with Person!
4394 .name = name
4395 \add_relative relative for relative in *relatives
4396
4397me = create_person "Leaf", [dad, mother, sister]
4398```
4399
4400</YueDisplay>
4401
4402In this usage, with can be seen as a special form of the K combinator.
4403
4404The expression in the with statement can also be an assignment, if you want to give a name to the expression.
4405
4406```yuescript
4407with str := "Hello"
4408 print "original:", str
4409 print "upper:", \upper!
4410```
4411<YueDisplay>
4412
4413```yue
4414with str := "Hello"
4415 print "original:", str
4416 print "upper:", \upper!
4417```
4418
4419</YueDisplay>
4420
4421You can access special keys with `[]` in a `with` statement.
4422
4423```yuescript
4424with tb
4425 [1] = 1
4426 print [2]
4427 with [abc]
4428 [3] = [2]\func!
4429 ["key-name"] = value
4430 [] = "abc" -- appending to "tb"
4431```
4432<YueDisplay>
4433
4434```yue
4435with tb
4436 [1] = 1
4437 print [2]
4438 with [abc]
4439 [3] = [2]\func!
4440 ["key-name"] = value
4441 [] = "abc" -- appending to "tb"
4442```
4443
4444</YueDisplay>
4445
4446`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.
4447
4448```yuescript
4449with? obj
4450 print obj.name
4451```
4452<YueDisplay>
4453
4454```yue
4455with? obj
4456 print obj.name
4457```
4458
4459</YueDisplay>
4460
4461## Do
4462
4463When used as a statement, do works just like it does in Lua.
4464
4465```yuescript
4466do
4467 var = "hello"
4468 print var
4469print var -- nil here
4470```
4471<YueDisplay>
4472
4473```yue
4474do
4475 var = "hello"
4476 print var
4477print var -- nil here
4478```
4479
4480</YueDisplay>
4481
4482YueScript'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.
4483
4484```yuescript
4485counter = do
4486 i = 0
4487 ->
4488 i += 1
4489 i
4490
4491print counter!
4492print counter!
4493```
4494<YueDisplay>
4495
4496```yue
4497counter = do
4498 i = 0
4499 ->
4500 i += 1
4501 i
4502
4503print counter!
4504print counter!
4505```
4506
4507</YueDisplay>
4508
4509```yuescript
4510tbl = {
4511 key: do
4512 print "assigning key!"
4513 1234
4514}
4515```
4516<YueDisplay>
4517
4518```yue
4519tbl = {
4520 key: do
4521 print "assigning key!"
4522 1234
4523}
4524```
4525
4526</YueDisplay>
4527
4528## Function Stubs
4529
4530It is common to pass a function from an object around as a value, for example, passing an instance method into a function as a callback. If the function expects the object it is operating on as the first argument then you must somehow bundle that object with the function so it can be called properly.
4531
4532The function stub syntax is a shorthand for creating a new closure function that bundles both the object and function. This new function calls the wrapped function in the correct context of the object.
4533
4534Its syntax is the same as calling an instance method with the \ operator but with no argument list provided.
4535
4536```yuescript
4537my_object = {
4538 value: 1000
4539 write: => print "the value:", @value
4540}
4541
4542run_callback = (func) ->
4543 print "running callback..."
4544 func!
4545
4546-- this will not work:
4547-- the function has to no reference to my_object
4548run_callback my_object.write
4549
4550-- function stub syntax
4551-- lets us bundle the object into a new function
4552run_callback my_object\write
4553```
4554<YueDisplay>
4555
4556```yue
4557my_object = {
4558 value: 1000
4559 write: => print "the value:", @value
4560}
4561
4562run_callback = (func) ->
4563 print "running callback..."
4564 func!
4565
4566-- this will not work:
4567-- the function has to no reference to my_object
4568run_callback my_object.write
4569
4570-- function stub syntax
4571-- lets us bundle the object into a new function
4572run_callback my_object\write
4573```
4574
4575</YueDisplay>
4576
4577## The Using Clause; Controlling Destructive Assignment
4578
4579While lexical scoping can be a great help in reducing the complexity of the code we write, things can get unwieldy as the code size increases. Consider the following snippet:
4580
4581```yuescript
4582i = 100
4583
4584-- many lines of code...
4585
4586my_func = ->
4587 i = 10
4588 while i > 0
4589 print i
4590 i -= 1
4591
4592my_func!
4593
4594print i -- will print 0
4595```
4596<YueDisplay>
4597
4598```yue
4599i = 100
4600
4601-- many lines of code...
4602
4603my_func = ->
4604 i = 10
4605 while i > 0
4606 print i
4607 i -= 1
4608
4609my_func!
4610
4611print i -- will print 0
4612```
4613
4614</YueDisplay>
4615
4616In 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.
4617
4618It 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.
4619
4620The using keyword lets us do that. using nil makes sure that no closed variables are overwritten in assignment. The using clause is placed after the argument list in a function, or in place of it if there are no arguments.
4621
4622```yuescript
4623i = 100
4624
4625my_func = (using nil) ->
4626 i = "hello" -- a new local variable is created here
4627
4628my_func!
4629print i -- prints 100, i is unaffected
4630```
4631<YueDisplay>
4632
4633```yue
4634i = 100
4635
4636my_func = (using nil) ->
4637 i = "hello" -- a new local variable is created here
4638
4639my_func!
4640print i -- prints 100, i is unaffected
4641```
4642
4643</YueDisplay>
4644
4645Multiple names can be separated by commas. Closure values can still be accessed, they just cant be modified:
4646
4647```yuescript
4648tmp = 1213
4649i, k = 100, 50
4650
4651my_func = (add using k, i) ->
4652 tmp = tmp + add -- a new local tmp is created
4653 i += tmp
4654 k += tmp
4655
4656my_func(22)
4657print i, k -- these have been updated
4658```
4659<YueDisplay>
4660
4661```yue
4662tmp = 1213
4663i, k = 100, 50
4664
4665my_func = (add using k, i) ->
4666 tmp = tmp + add -- a new local tmp is created
4667 i += tmp
4668 k += tmp
4669
4670my_func(22)
4671print i, k -- these have been updated
4672```
4673
4674</YueDisplay>
4675
4676## The YueScript Library
4677
4678Access it by `require("yue")`.
4679
4680### yue
4681
4682**Description:**
4683
4684The YueScript language library.
4685
4686#### version
4687
4688**Type:** Field.
4689
4690**Description:**
4691
4692The YueScript version.
4693
4694**Signature:**
4695```lua
4696version: string
4697```
4698
4699#### dirsep
4700
4701**Type:** Field.
4702
4703**Description:**
4704
4705The file separator for the current platform.
4706
4707**Signature:**
4708```lua
4709dirsep: string
4710```
4711
4712#### yue_compiled
4713
4714**Type:** Field.
4715
4716**Description:**
4717
4718The compiled module code cache.
4719
4720**Signature:**
4721```lua
4722yue_compiled: {string: string}
4723```
4724
4725#### to_lua
4726
4727**Type:** Function.
4728
4729**Description:**
4730
4731The YueScript compiling function. It compiles the YueScript code to Lua code.
4732
4733**Signature:**
4734```lua
4735to_lua: function(code: string, config?: Config):
4736 --[[codes]] string | nil,
4737 --[[error]] string | nil,
4738 --[[globals]] {{string, integer, integer}} | nil
4739```
4740
4741**Parameters:**
4742
4743| Parameter | Type | Description |
4744| --- | --- | --- |
4745| code | string | The YueScript code. |
4746| config | Config | [Optional] The compiler options. |
4747
4748**Returns:**
4749
4750| Return Type | Description |
4751| --- | --- |
4752| string \| nil | The compiled Lua code, or nil if the compilation failed. |
4753| string \| nil | The error message, or nil if the compilation succeeded. |
4754| {{string, integer, integer}} \| nil | The global variables appearing in the code (with name, row and column), or nil if the compiler option `lint_global` is false. |
4755
4756#### file_exist
4757
4758**Type:** Function.
4759
4760**Description:**
4761
4762The source file existence checking function. Can be overridden to customize the behavior.
4763
4764**Signature:**
4765```lua
4766file_exist: function(filename: string): boolean
4767```
4768
4769**Parameters:**
4770
4771| Parameter | Type | Description |
4772| --- | --- | --- |
4773| filename | string | The file name. |
4774
4775**Returns:**
4776
4777| Return Type | Description |
4778| --- | --- |
4779| boolean | Whether the file exists. |
4780
4781#### read_file
4782
4783**Type:** Function.
4784
4785**Description:**
4786
4787The source file reading function. Can be overridden to customize the behavior.
4788
4789**Signature:**
4790```lua
4791read_file: function(filename: string): string
4792```
4793
4794**Parameters:**
4795
4796| Parameter | Type | Description |
4797| --- | --- | --- |
4798| filename | string | The file name. |
4799
4800**Returns:**
4801
4802| Return Type | Description |
4803| --- | --- |
4804| string | The file content. |
4805
4806#### insert_loader
4807
4808**Type:** Function.
4809
4810**Description:**
4811
4812Insert the YueScript loader to the package loaders (searchers).
4813
4814**Signature:**
4815```lua
4816insert_loader: function(pos?: integer): boolean
4817```
4818
4819**Parameters:**
4820
4821| Parameter | Type | Description |
4822| --- | --- | --- |
4823| pos | integer | [Optional] The position to insert the loader. Default is 3. |
4824
4825**Returns:**
4826
4827| Return Type | Description |
4828| --- | --- |
4829| boolean | Whether the loader is inserted successfully. It will fail if the loader is already inserted. |
4830
4831#### remove_loader
4832
4833**Type:** Function.
4834
4835**Description:**
4836
4837Remove the YueScript loader from the package loaders (searchers).
4838
4839**Signature:**
4840```lua
4841remove_loader: function(): boolean
4842```
4843
4844**Returns:**
4845
4846| Return Type | Description |
4847| --- | --- |
4848| boolean | Whether the loader is removed successfully. It will fail if the loader is not inserted. |
4849
4850#### loadstring
4851
4852**Type:** Function.
4853
4854**Description:**
4855
4856Loads YueScript code from a string into a function.
4857
4858**Signature:**
4859```lua
4860loadstring: function(input: string, chunkname: string, env: table, config?: Config):
4861 --[[loaded function]] nil | function(...: any): (any...),
4862 --[[error]] string | nil
4863```
4864
4865**Parameters:**
4866
4867| Parameter | Type | Description |
4868| --- | --- | --- |
4869| input | string | The YueScript code. |
4870| chunkname | string | The name of the code chunk. |
4871| env | table | The environment table. |
4872| config | Config | [Optional] The compiler options. |
4873
4874**Returns:**
4875
4876| Return Type | Description |
4877| --- | --- |
4878| function \| nil | The loaded function, or nil if the loading failed. |
4879| string \| nil | The error message, or nil if the loading succeeded. |
4880
4881#### loadstring
4882
4883**Type:** Function.
4884
4885**Description:**
4886
4887Loads YueScript code from a string into a function.
4888
4889**Signature:**
4890```lua
4891loadstring: function(input: string, chunkname: string, config?: Config):
4892 --[[loaded function]] nil | function(...: any): (any...),
4893 --[[error]] string | nil
4894```
4895
4896**Parameters:**
4897
4898| Parameter | Type | Description |
4899| --- | --- | --- |
4900| input | string | The YueScript code. |
4901| chunkname | string | The name of the code chunk. |
4902| config | Config | [Optional] The compiler options. |
4903
4904**Returns:**
4905
4906| Return Type | Description |
4907| --- | --- |
4908| function \| nil | The loaded function, or nil if the loading failed. |
4909| string \| nil | The error message, or nil if the loading succeeded. |
4910
4911#### loadstring
4912
4913**Type:** Function.
4914
4915**Description:**
4916
4917Loads YueScript code from a string into a function.
4918
4919**Signature:**
4920```lua
4921loadstring: function(input: string, config?: Config):
4922 --[[loaded function]] nil | function(...: any): (any...),
4923 --[[error]] string | nil
4924```
4925
4926**Parameters:**
4927
4928| Parameter | Type | Description |
4929| --- | --- | --- |
4930| input | string | The YueScript code. |
4931| config | Config | [Optional] The compiler options. |
4932
4933**Returns:**
4934
4935| Return Type | Description |
4936| --- | --- |
4937| function \| nil | The loaded function, or nil if the loading failed. |
4938| string \| nil | The error message, or nil if the loading succeeded. |
4939
4940#### loadfile
4941
4942**Type:** Function.
4943
4944**Description:**
4945
4946Loads YueScript code from a file into a function.
4947
4948**Signature:**
4949```lua
4950loadfile: function(filename: string, env: table, config?: Config):
4951 nil | function(...: any): (any...),
4952 string | nil
4953```
4954
4955**Parameters:**
4956
4957| Parameter | Type | Description |
4958| --- | --- | --- |
4959| filename | string | The file name. |
4960| env | table | The environment table. |
4961| config | Config | [Optional] The compiler options. |
4962
4963**Returns:**
4964
4965| Return Type | Description |
4966| --- | --- |
4967| function \| nil | The loaded function, or nil if the loading failed. |
4968| string \| nil | The error message, or nil if the loading succeeded. |
4969
4970#### loadfile
4971
4972**Type:** Function.
4973
4974**Description:**
4975
4976Loads YueScript code from a file into a function.
4977
4978**Signature:**
4979```lua
4980loadfile: function(filename: string, config?: Config):
4981 nil | function(...: any): (any...),
4982 string | nil
4983```
4984
4985**Parameters:**
4986
4987| Parameter | Type | Description |
4988| --- | --- | --- |
4989| filename | string | The file name. |
4990| config | Config | [Optional] The compiler options. |
4991
4992**Returns:**
4993
4994| Return Type | Description |
4995| --- | --- |
4996| function \| nil | The loaded function, or nil if the loading failed. |
4997| string \| nil | The error message, or nil if the loading succeeded. |
4998
4999#### dofile
5000
5001**Type:** Function.
5002
5003**Description:**
5004
5005Loads YueScript code from a file into a function and executes it.
5006
5007**Signature:**
5008```lua
5009dofile: function(filename: string, env: table, config?: Config): any...
5010```
5011
5012**Parameters:**
5013
5014| Parameter | Type | Description |
5015| --- | --- | --- |
5016| filename | string | The file name. |
5017| env | table | The environment table. |
5018| config | Config | [Optional] The compiler options. |
5019
5020**Returns:**
5021
5022| Return Type | Description |
5023| --- | --- |
5024| any... | The return values of the loaded function. |
5025
5026#### dofile
5027
5028**Type:** Function.
5029
5030**Description:**
5031
5032Loads YueScript code from a file into a function and executes it.
5033
5034**Signature:**
5035```lua
5036dofile: function(filename: string, config?: Config): any...
5037```
5038
5039**Parameters:**
5040
5041| Parameter | Type | Description |
5042| --- | --- | --- |
5043| filename | string | The file name. |
5044| config | Config | [Optional] The compiler options. |
5045
5046**Returns:**
5047
5048| Return Type | Description |
5049| --- | --- |
5050| any... | The return values of the loaded function. |
5051
5052#### find_modulepath
5053
5054**Type:** Function.
5055
5056**Description:**
5057
5058Resolves the YueScript module name to the file path.
5059
5060**Signature:**
5061```lua
5062find_modulepath: function(name: string): string
5063```
5064
5065**Parameters:**
5066
5067| Parameter | Type | Description |
5068| --- | --- | --- |
5069| name | string | The module name. |
5070
5071**Returns:**
5072
5073| Return Type | Description |
5074| --- | --- |
5075| string | The file path. |
5076
5077#### pcall
5078
5079**Type:** Function.
5080
5081**Description:**
5082
5083Calls a function in protected mode.
5084Catches any errors and returns a status code and results or error object.
5085Rewrites the error line number to the original line number in the YueScript code when errors occur.
5086
5087**Signature:**
5088```lua
5089pcall: function(f: function, ...: any): boolean, any...
5090```
5091
5092**Parameters:**
5093
5094| Parameter | Type | Description |
5095| --- | --- | --- |
5096| f | function | The function to call. |
5097| ... | any | Arguments to pass to the function. |
5098
5099**Returns:**
5100
5101| Return Type | Description |
5102| --- | --- |
5103| boolean, ... | Status code and function results or error object. |
5104
5105#### require
5106
5107**Type:** Function.
5108
5109**Description:**
5110
5111Loads a given module. Can be either a Lua module or a YueScript module.
5112Rewrites the error line number to the original line number in the YueScript code if the module is a YueScript module and loading fails.
5113
5114**Signature:**
5115```lua
5116require: function(name: string): any...
5117```
5118
5119**Parameters:**
5120
5121| Parameter | Type | Description |
5122| --- | --- | --- |
5123| modname | string | The name of the module to load. |
5124
5125**Returns:**
5126
5127| Return Type | Description |
5128| --- | --- |
5129| any | The value stored at package.loaded[modname] if the module is already loaded.Otherwise, tries to find a loader and returns the final value of package.loaded[modname] and a loader data as a second result. |
5130
5131#### p
5132
5133**Type:** Function.
5134
5135**Description:**
5136
5137Inspects the structures of the passed values and prints string representations.
5138
5139**Signature:**
5140```lua
5141p: function(...: any)
5142```
5143
5144**Parameters:**
5145
5146| Parameter | Type | Description |
5147| --- | --- | --- |
5148| ... | any | The values to inspect. |
5149
5150#### options
5151
5152**Type:** Field.
5153
5154**Description:**
5155
5156The current compiler options.
5157
5158**Signature:**
5159```lua
5160options: Config.Options
5161```
5162
5163#### traceback
5164
5165**Type:** Function.
5166
5167**Description:**
5168
5169The traceback function that rewrites the stack trace line numbers to the original line numbers in the YueScript code.
5170
5171**Signature:**
5172```lua
5173traceback: function(message: string): string
5174```
5175
5176**Parameters:**
5177
5178| Parameter | Type | Description |
5179| --- | --- | --- |
5180| message | string | The traceback message. |
5181
5182**Returns:**
5183
5184| Return Type | Description |
5185| --- | --- |
5186| string | The rewritten traceback message. |
5187
5188#### is_ast
5189
5190**Type:** Function.
5191
5192**Description:**
5193
5194Checks whether the code matches the specified AST.
5195
5196**Signature:**
5197```lua
5198is_ast: function(astName: string, code: string): boolean
5199```
5200
5201**Parameters:**
5202
5203| Parameter | Type | Description |
5204| --- | --- | --- |
5205| astName | string | The AST name. |
5206| code | string | The code. |
5207
5208**Returns:**
5209
5210| Return Type | Description |
5211| --- | --- |
5212| boolean | Whether the code matches the AST. |
5213
5214#### AST
5215
5216**Type:** Field.
5217
5218**Description:**
5219
5220The AST type definition with name, row, column and sub nodes.
5221
5222**Signature:**
5223```lua
5224type AST = {string, integer, integer, any}
5225```
5226
5227#### to_ast
5228
5229**Type:** Function.
5230
5231**Description:**
5232
5233Converts the code to the AST.
5234
5235**Signature:**
5236```lua
5237to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean):
5238 --[[AST]] AST | nil,
5239 --[[error]] nil | string
5240```
5241
5242**Parameters:**
5243
5244| Parameter | Type | Description |
5245| --- | --- | --- |
5246| code | string | The code. |
5247| flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. |
5248| astName | string | [Optional] The AST name. Default is "File". |
5249| reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is false. |
5250
5251**Returns:**
5252
5253| Return Type | Description |
5254| --- | --- |
5255| AST \| nil | The AST, or nil if the conversion failed. |
5256| string \| nil | The error message, or nil if the conversion succeeded. |
5257
5258#### format
5259
5260**Type:** Function.
5261
5262**Description:**
5263
5264Formats the YueScript code.
5265
5266**Signature:**
5267```lua
5268format: function(code: string, tabSize?: number, reserveComment?: boolean): string
5269```
5270
5271**Parameters:**
5272
5273| Parameter | Type | Description |
5274| --- | --- | --- |
5275| code | string | The code. |
5276| tabSize | integer | [Optional] The tab size. Default is 4. |
5277| reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is true. |
5278
5279**Returns:**
5280
5281| Return Type | Description |
5282| --- | --- |
5283| string | The formatted code. |
5284
5285#### __call
5286
5287**Type:** Metamethod.
5288
5289**Description:**
5290
5291Requires the YueScript module.
5292Rewrites the error line number to the original line number in the YueScript code when loading fails.
5293
5294**Signature:**
5295```lua
5296metamethod __call: function(self: yue, module: string): any...
5297```
5298
5299**Parameters:**
5300
5301| Parameter | Type | Description |
5302| --- | --- | --- |
5303| module | string | The module name. |
5304
5305**Returns:**
5306
5307| Return Type | Description |
5308| --- | --- |
5309| any | The module value. |
5310
5311### Config
5312
5313**Description:**
5314
5315The compiler compile options.
5316
5317#### lint_global
5318
5319**Type:** Field.
5320
5321**Description:**
5322
5323Whether the compiler should collect the global variables appearing in the code.
5324
5325**Signature:**
5326```lua
5327lint_global: boolean
5328```
5329
5330#### implicit_return_root
5331
5332**Type:** Field.
5333
5334**Description:**
5335
5336Whether the compiler should do an implicit return for the root code block.
5337
5338**Signature:**
5339```lua
5340implicit_return_root: boolean
5341```
5342
5343#### reserve_line_number
5344
5345**Type:** Field.
5346
5347**Description:**
5348
5349Whether the compiler should reserve the original line number in the compiled code.
5350
5351**Signature:**
5352```lua
5353reserve_line_number: boolean
5354```
5355
5356#### reserve_comment
5357
5358**Type:** Field.
5359
5360**Description:**
5361
5362Whether the compiler should reserve the original comments in the compiled code.
5363
5364**Signature:**
5365```lua
5366reserve_comment: boolean
5367```
5368
5369#### space_over_tab
5370
5371**Type:** Field.
5372
5373**Description:**
5374
5375Whether the compiler should use the space character instead of the tab character in the compiled code.
5376
5377**Signature:**
5378```lua
5379space_over_tab: boolean
5380```
5381
5382#### same_module
5383
5384**Type:** Field.
5385
5386**Description:**
5387
5388Whether the compiler should treat the code to be compiled as the same currently being compiled module. For internal use only.
5389
5390**Signature:**
5391```lua
5392same_module: boolean
5393```
5394
5395#### line_offset
5396
5397**Type:** Field.
5398
5399**Description:**
5400
5401Whether the compiler error message should include the line number offset. For internal use only.
5402
5403**Signature:**
5404```lua
5405line_offset: integer
5406```
5407
5408#### yue.Config.LuaTarget
5409
5410**Type:** Enumeration.
5411
5412**Description:**
5413
5414The target Lua version enumeration.
5415
5416**Signature:**
5417```lua
5418enum LuaTarget
5419 "5.1"
5420 "5.2"
5421 "5.3"
5422 "5.4"
5423 "5.5"
5424end
5425```
5426
5427#### options
5428
5429**Type:** Field.
5430
5431**Description:**
5432
5433The extra options to be passed to the compilation function.
5434
5435**Signature:**
5436```lua
5437options: Options
5438```
5439
5440### Options
5441
5442**Description:**
5443
5444The extra compiler options definition.
5445
5446#### target
5447
5448**Type:** Field.
5449
5450**Description:**
5451
5452The target Lua version for the compilation.
5453
5454**Signature:**
5455```lua
5456target: LuaTarget
5457```
5458
5459#### path
5460
5461**Type:** Field.
5462
5463**Description:**
5464
5465The extra module search path.
5466
5467**Signature:**
5468```lua
5469path: string
5470```
5471
5472#### dump_locals
5473
5474**Type:** Field.
5475
5476**Description:**
5477
5478Whether to dump the local variables in the traceback error message. Default is false.
5479
5480**Signature:**
5481```lua
5482dump_locals: boolean
5483```
5484
5485#### simplified
5486
5487**Type:** Field.
5488
5489**Description:**
5490
5491Whether to simplify the error message. Default is true.
5492
5493**Signature:**
5494```lua
5495simplified: boolean
5496```
5497
5498## Licence: MIT
5499
5500Copyright (c) 2017-2026 Li Jin \<dragon-fly@qq.com\>
5501
5502Permission is hereby granted, free of charge, to any person obtaining a copy
5503of this software and associated documentation files (the "Software"), to deal
5504in the Software without restriction, including without limitation the rights
5505to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5506copies of the Software, and to permit persons to whom the Software is
5507furnished to do so, subject to the following conditions:
5508
5509The above copyright notice and this permission notice shall be included in all
5510copies or substantial portions of the Software.
5511
5512THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5513IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5514FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5515AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5516LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
5517OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
5518SOFTWARE.
5519
5520<CompilerModal />
diff --git a/doc/docs/doc/installation.md b/doc/docs/doc/installation.md
new file mode 100644
index 0000000..a93ddfd
--- /dev/null
+++ b/doc/docs/doc/installation.md
@@ -0,0 +1,43 @@
1# Installation
2
3## Lua Module
4
5Install [luarocks](https://luarocks.org), a package manager for Lua modules. Then install it as a Lua module and executable with:
6
7```shell
8luarocks install yuescript
9```
10
11Or you can build `yue.so` file with:
12
13```shell
14make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua
15```
16
17Then get the binary file from path **bin/shared/yue.so**.
18
19## Build Binary Tool
20
21Clone this repo, then build and install executable with:
22
23```shell
24make install
25```
26
27Build YueScript tool without macro feature:
28
29```shell
30make install NO_MACRO=true
31```
32
33Build YueScript tool without built-in Lua binary:
34
35```shell
36make install NO_LUA=true
37```
38
39## Download Precompiled Binary
40
41You can download precompiled binary files, including binary executable files compatible with different Lua versions and library files.
42
43Download precompiled binary files from [here](https://github.com/IppClub/YueScript/releases).
diff --git a/doc/docs/doc/introduction.md b/doc/docs/doc/introduction.md
new file mode 100644
index 0000000..a9a9389
--- /dev/null
+++ b/doc/docs/doc/introduction.md
@@ -0,0 +1,105 @@
1# Introduction
2
3YueScript is a dynamic language that compiles to Lua. And it's a [MoonScript](https://github.com/leafo/moonscript) dialect. The codes written in YueScript are expressive and extremely concise. And it is suitable for writing some changing application logic with more maintainable codes and runs in a Lua embeded environment such as games or website servers.
4
5Yue (月) is the name of moon in Chinese and it's pronounced as [jyɛ].
6
7## An Overview of YueScript
8
9```yuescript
10-- import syntax
11import p, to_lua from "yue"
12
13-- object literals
14inventory =
15 equipment:
16 - "sword"
17 - "shield"
18 items:
19 - name: "potion"
20 count: 10
21 - name: "bread"
22 count: 3
23
24-- list comprehension
25map = (arr, action) ->
26 [action item for item in *arr]
27
28filter = (arr, cond) ->
29 [item for item in *arr when cond item]
30
31reduce = (arr, init, action): init ->
32 init = action init, item for item in *arr
33
34-- pipe operator
35[1, 2, 3]
36 |> map (x) -> x * 2
37 |> filter (x) -> x > 4
38 |> reduce 0, (a, b) -> a + b
39 |> print
40
41-- metatable manipulation
42apple =
43 size: 15
44 <index>:
45 color: 0x00ffff
46
47with apple
48 p .size, .color, .<index> if .<>?
49
50-- js-like export syntax
51export 🌛 = "月之脚本"
52```
53
54<YueDisplay>
55
56```yue
57-- import syntax
58import p, to_lua from "yue"
59
60-- object literals
61inventory =
62 equipment:
63 - "sword"
64 - "shield"
65 items:
66 - name: "potion"
67 count: 10
68 - name: "bread"
69 count: 3
70
71-- list comprehension
72map = (arr, action) ->
73 [action item for item in *arr]
74
75filter = (arr, cond) ->
76 [item for item in *arr when cond item]
77
78reduce = (arr, init, action): init ->
79 init = action init, item for item in *arr
80
81-- pipe operator
82[1, 2, 3]
83 |> map (x) -> x * 2
84 |> filter (x) -> x > 4
85 |> reduce 0, (a, b) -> a + b
86 |> print
87
88-- metatable manipulation
89apple =
90 size: 15
91 <index>:
92 color: 0x00ffff
93
94with apple
95 p .size, .color, .<index> if .<>?
96
97-- js-like export syntax
98export 🌛 = "月之脚本"
99```
100
101</YueDisplay>
102
103## About Dora SSR
104
105YueScript is being developed and maintained alongside the open-source game engine [Dora SSR](https://github.com/Dora-SSR/Dora-SSR). It has been used to create engine tools, game demos and prototypes, validating its capabilities in real-world scenarios while enhancing the Dora SSR development experience. \ No newline at end of file
diff --git a/doc/docs/doc/licence-mit.md b/doc/docs/doc/licence-mit.md
new file mode 100644
index 0000000..253298f
--- /dev/null
+++ b/doc/docs/doc/licence-mit.md
@@ -0,0 +1,23 @@
1# Licence: MIT
2
3Copyright (c) 2017-2026 Li Jin \<dragon-fly@qq.com\>
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
22
23<CompilerModal />
diff --git a/doc/docs/doc/line-decorators.md b/doc/docs/doc/line-decorators.md
new file mode 100644
index 0000000..292bc77
--- /dev/null
+++ b/doc/docs/doc/line-decorators.md
@@ -0,0 +1,44 @@
1# Line Decorators
2
3For convenience, the for loop and if statement can be applied to single statements at the end of the line:
4
5```yuescript
6print "hello world" if name == "Rob"
7```
8<YueDisplay>
9
10```yue
11print "hello world" if name == "Rob"
12```
13
14</YueDisplay>
15
16And with basic loops:
17
18```yuescript
19print "item: ", item for item in *items
20```
21<YueDisplay>
22
23```yue
24print "item: ", item for item in *items
25```
26
27</YueDisplay>
28
29And with while loops:
30
31```yuescript
32game\update! while game\isRunning!
33
34reader\parse_line! until reader\eof!
35```
36<YueDisplay>
37
38```yue
39game\update! while game\isRunning!
40
41reader\parse_line! until reader\eof!
42```
43
44</YueDisplay>
diff --git a/doc/docs/doc/literals.md b/doc/docs/doc/literals.md
new file mode 100644
index 0000000..e097c62
--- /dev/null
+++ b/doc/docs/doc/literals.md
@@ -0,0 +1,110 @@
1# Literals
2
3All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**.
4
5Unlike Lua, Line breaks are allowed inside of single and double quote strings without an escape sequence:
6
7```yuescript
8some_string = "Here is a string
9 that has a line break in it."
10
11-- You can mix expressions into string literals using #{} syntax.
12-- String interpolation is only available in double quoted strings.
13print "I am #{math.random! * 100}% sure."
14```
15<YueDisplay>
16
17```yue
18some_string = "Here is a string
19 that has a line break in it."
20
21-- You can mix expressions into string literals using #{} syntax.
22-- String interpolation is only available in double quoted strings.
23print "I am #{math.random! * 100}% sure."
24```
25
26</YueDisplay>
27
28## Number Literals
29
30You can use underscores in a number literal to increase readability.
31
32```yuescript
33integer = 1_000_000
34hex = 0xEF_BB_BF
35binary = 0B10011
36```
37<YueDisplay>
38
39```yue
40integer = 1_000_000
41hex = 0xEF_BB_BF
42binary = 0B10011
43```
44
45</YueDisplay>
46
47## YAML Multiline String
48
49The `|` prefix introduces a YAML-style multiline string literal:
50
51```yuescript
52str = |
53 key: value
54 list:
55 - item1
56 - #{expr}
57```
58<YueDisplay>
59
60```yue
61str = |
62 key: value
63 list:
64 - item1
65 - #{expr}
66```
67
68</YueDisplay>
69
70This 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)`.
71
72YAML 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.
73
74```yuescript
75fn = ->
76 str = |
77 foo:
78 bar: baz
79 return str
80```
81<YueDisplay>
82
83```yue
84fn = ->
85 str = |
86 foo:
87 bar: baz
88 return str
89```
90
91</YueDisplay>
92
93Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures.
94
95All 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.
96
97```yuescript
98str = |
99 path: "C:\Program Files\App"
100 note: 'He said: "#{Hello}!"'
101```
102<YueDisplay>
103
104```yue
105str = |
106 path: "C:\Program Files\App"
107 note: 'He said: "#{Hello}!"'
108```
109
110</YueDisplay>
diff --git a/doc/docs/doc/macro.md b/doc/docs/doc/macro.md
new file mode 100644
index 0000000..917c20e
--- /dev/null
+++ b/doc/docs/doc/macro.md
@@ -0,0 +1,274 @@
1# Macro
2
3## Common Usage
4
5Macro function is used for evaluating a string in the compile time and insert the generated codes into final compilation.
6
7```yuescript
8macro PI2 = -> math.pi * 2
9area = $PI2 * 5
10
11macro HELLO = -> "'hello world'"
12print $HELLO
13
14macro config = (debugging) ->
15 global debugMode = debugging == "true"
16 ""
17
18macro asserts = (cond) ->
19 debugMode and "assert #{cond}" or ""
20
21macro assert = (cond) ->
22 debugMode and "assert #{cond}" or "#{cond}"
23
24$config true
25$asserts item ~= nil
26
27$config false
28value = $assert item
29
30-- the passed expressions are treated as strings
31macro and = (...) -> "#{ table.concat {...}, ' and ' }"
32if $and f1!, f2!, f3!
33 print "OK"
34```
35<YueDisplay>
36
37```yue
38macro PI2 = -> math.pi * 2
39area = $PI2 * 5
40
41macro HELLO = -> "'hello world'"
42print $HELLO
43
44macro config = (debugging) ->
45 global debugMode = debugging == "true"
46 ""
47
48macro asserts = (cond) ->
49 debugMode and "assert #{cond}" or ""
50
51macro assert = (cond) ->
52 debugMode and "assert #{cond}" or "#{cond}"
53
54$config true
55$asserts item ~= nil
56
57$config false
58value = $assert item
59
60-- the passed expressions are treated as strings
61macro and = (...) -> "#{ table.concat {...}, ' and ' }"
62if $and f1!, f2!, f3!
63 print "OK"
64```
65
66</YueDisplay>
67
68## Insert Raw Codes
69
70A macro function can either return a YueScript string or a config table containing Lua codes.
71```yuescript
72macro yueFunc = (var) -> "local #{var} = ->"
73$yueFunc funcA
74funcA = -> "fail to assign to the Yue macro defined variable"
75
76macro luaFunc = (var) -> {
77 code: "local function #{var}() end"
78 type: "lua"
79}
80$luaFunc funcB
81funcB = -> "fail to assign to the Lua macro defined variable"
82
83macro lua = (code) -> {
84 :code
85 type: "lua"
86}
87
88-- the raw string leading and ending symbols are auto trimed
89$lua[==[
90-- raw Lua codes insertion
91if cond then
92 print("output")
93end
94]==]
95```
96<YueDisplay>
97
98```yue
99macro yueFunc = (var) -> "local #{var} = ->"
100$yueFunc funcA
101funcA = -> "fail to assign to the Yue macro defined variable"
102
103macro luaFunc = (var) -> {
104 code: "local function #{var}() end"
105 type: "lua"
106}
107$luaFunc funcB
108funcB = -> "fail to assign to the Lua macro defined variable"
109
110macro lua = (code) -> {
111 :code
112 type: "lua"
113}
114
115-- the raw string leading and ending symbols are auto trimed
116$lua[==[
117-- raw Lua codes insertion
118if cond then
119 print("output")
120end
121]==]
122```
123
124</YueDisplay>
125
126## Export Macro
127
128Macro functions can be exported from a module and get imported in another module. You have to put export macro functions in a single file to be used, and only macro definition, macro importing and macro expansion in place can be put into the macro exporting module.
129```yuescript
130-- file: utils.yue
131export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
132export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
133export macro foreach = (items, action) -> "for _ in *#{items}
134 #{action}"
135
136-- file main.yue
137import "utils" as {
138 $, -- symbol to import all macros
139 $foreach: $each -- rename macro $foreach to $each
140}
141[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
142```
143<YueDisplay>
144
145```yue
146-- file: utils.yue
147export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
148export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
149export macro foreach = (items, action) -> "for _ in *#{items}
150 #{action}"
151-- file main.yue
152-- import function is not available in browser, try it in a real environment
153--[[
154import "utils" as {
155 $, -- symbol to import all macros
156 $foreach: $each -- rename macro $foreach to $each
157}
158[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
159]]
160```
161
162</YueDisplay>
163
164## Builtin Macro
165
166There are some builtin macros but you can override them by declaring macros with the same names.
167```yuescript
168print $FILE -- get string of current module name
169print $LINE -- get number 2
170```
171<YueDisplay>
172
173```yue
174print $FILE -- get string of current module name
175print $LINE -- get number 2
176```
177
178</YueDisplay>
179
180## Generating Macros with Macros
181
182In YueScript, macro functions allow you to generate code at compile time. By nesting macro functions, you can create more complex generation patterns. This feature enables you to define a macro function that generates another macro function, allowing for more dynamic code generation.
183
184```yuescript
185macro Enum = (...) ->
186 items = {...}
187 itemSet = {item, true for item in *items}
188 (item) ->
189 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
190 "\"#{item}\""
191
192macro BodyType = $Enum(
193 Static
194 Dynamic
195 Kinematic
196)
197
198print "Valid enum type:", $BodyType Static
199-- print "Compilation error with enum type:", $BodyType Unknown
200```
201
202<YueDisplay>
203
204```yue
205macro Enum = (...) ->
206 items = {...}
207 itemSet = {item, true for item in *items}
208 (item) ->
209 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
210 "\"#{item}\""
211
212macro BodyType = $Enum(
213 Static
214 Dynamic
215 Kinematic
216)
217
218print "Valid enum type:", $BodyType Static
219-- print "Compilation error with enum type:", $BodyType Unknown
220```
221
222</YueDisplay>
223
224## Argument Validation
225
226You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time.
227
228```yuescript
229macro printNumAndStr = (num `Num, str `String) -> |
230 print(
231 #{num}
232 #{str}
233 )
234
235$printNumAndStr 123, "hello"
236```
237<YueDisplay>
238
239```yue
240macro printNumAndStr = (num `Num, str `String) -> |
241 print(
242 #{num}
243 #{str}
244 )
245
246$printNumAndStr 123, "hello"
247```
248
249</YueDisplay>
250
251If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place.
252
253```yuescript
254macro printNumAndStr = (num, str) ->
255 error "expected Num as first argument" unless $is_ast Num, num
256 error "expected String as second argument" unless $is_ast String, str
257 "print(#{num}, #{str})"
258
259$printNumAndStr 123, "hello"
260```
261<YueDisplay>
262
263```yue
264macro printNumAndStr = (num, str) ->
265 error "expected Num as first argument" unless $is_ast Num, num
266 error "expected String as second argument" unless $is_ast String, str
267 "print(#{num}, #{str})"
268
269$printNumAndStr 123, "hello"
270```
271
272</YueDisplay>
273
274For 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).
diff --git a/doc/docs/doc/module.md b/doc/docs/doc/module.md
new file mode 100644
index 0000000..c955092
--- /dev/null
+++ b/doc/docs/doc/module.md
@@ -0,0 +1,245 @@
1# Module
2
3## Import
4
5The import statement is a syntax sugar for requiring a module or help extracting items from an imported module. The imported items are const by default.
6
7```yuescript
8-- used as table destructuring
9do
10 import insert, concat from table
11 -- report error when assigning to insert, concat
12 import C, Ct, Cmt from require "lpeg"
13 -- shortcut for implicit requiring
14 import x, y, z from 'mymodule'
15 -- import with Python style
16 from 'module' import a, b, c
17
18-- shortcut for requring a module
19do
20 import 'module'
21 import 'module_x'
22 import "d-a-s-h-e-s"
23 import "module.part"
24
25-- requring module with aliasing or table destructuring
26do
27 import "player" as PlayerModule
28 import "lpeg" as :C, :Ct, :Cmt
29 import "export" as {one, two, Something:{umm:{ch}}}
30```
31<YueDisplay>
32
33```yue
34-- used as table destructuring
35do
36 import insert, concat from table
37 -- report error when assigning to insert, concat
38 import C, Ct, Cmt from require "lpeg"
39 -- shortcut for implicit requiring
40 import x, y, z from 'mymodule'
41 -- import with Python style
42 from 'module' import a, b, c
43
44-- shortcut for requring a module
45do
46 import 'module'
47 import 'module_x'
48 import "d-a-s-h-e-s"
49 import "module.part"
50
51-- requring module with aliasing or table destructuring
52do
53 import "player" as PlayerModule
54 import "lpeg" as :C, :Ct, :Cmt
55 import "export" as {one, two, Something:{umm:{ch}}}
56```
57
58</YueDisplay>
59
60## Import Global
61
62You can import specific globals into local variables with `import`. When importing a chain of global variable accessings, the last field will be assigned to the local variable.
63
64```yuescript
65do
66 import tostring
67 import table.concat
68 print concat ["a", tostring 1]
69```
70<YueDisplay>
71
72```yue
73do
74 import tostring
75 import table.concat
76 print concat ["a", tostring 1]
77```
78
79</YueDisplay>
80
81### Automatic Global Variable Import
82
83You can place `import global` at the top of a block to automatically import all names that have not been explicitly declared or assigned in the current scope as globals. These implicit imports are treated as local consts that reference the corresponding globals at the position of the statement.
84
85Names that are explicitly declared as globals in the same scope will not be imported, so you can still assign to them.
86
87```yuescript
88do
89 import global
90 print "hello"
91 math.random 3
92 -- print = nil -- error: imported globals are const
93
94do
95 -- explicit global variable will not be imported
96 import global
97 global FLAG
98 print FLAG
99 FLAG = 123
100```
101<YueDisplay>
102
103```yue
104do
105 import global
106 print "hello"
107 math.random 3
108 -- print = nil -- error: imported globals are const
109
110do
111 -- explicit global variable will not be imported
112 import global
113 global FLAG
114 print FLAG
115 FLAG = 123
116```
117
118</YueDisplay>
119
120## Export
121
122The export statement offers a concise way to define modules.
123
124### Named Export
125
126Named export will define a local variable as well as adding a field in the exported table.
127
128```yuescript
129export a, b, c = 1, 2, 3
130export cool = "cat"
131
132export What = if this
133 "abc"
134else
135 "def"
136
137export y = ->
138 hallo = 3434
139
140export class Something
141 umm: "cool"
142```
143<YueDisplay>
144
145```yue
146export a, b, c = 1, 2, 3
147export cool = "cat"
148
149export What = if this
150 "abc"
151else
152 "def"
153
154export y = ->
155 hallo = 3434
156
157export class Something
158 umm: "cool"
159```
160
161</YueDisplay>
162
163Doing named export with destructuring.
164
165```yuescript
166export :loadstring, to_lua: tolua = yue
167export {itemA: {:fieldA = 'default'}} = tb
168```
169<YueDisplay>
170
171```yue
172export :loadstring, to_lua: tolua = yue
173export {itemA: {:fieldA = 'default'}} = tb
174```
175
176</YueDisplay>
177
178Export named items from module without creating local variables.
179
180```yuescript
181export.itemA = tb
182export.<index> = items
183export["a-b-c"] = 123
184```
185<YueDisplay>
186
187```yue
188export.itemA = tb
189export.<index> = items
190export["a-b-c"] = 123
191```
192
193</YueDisplay>
194
195### Unnamed Export
196
197Unnamed export will add the target item into the array part of the exported table.
198
199```yuescript
200d, e, f = 3, 2, 1
201export d, e, f
202
203export if this
204 123
205else
206 456
207
208export with tmp
209 j = 2000
210```
211<YueDisplay>
212
213```yue
214d, e, f = 3, 2, 1
215export d, e, f
216
217export if this
218 123
219else
220 456
221
222export with tmp
223 j = 2000
224```
225
226</YueDisplay>
227
228### Default Export
229
230Using the **default** keyword in export statement to replace the exported table with any thing.
231
232```yuescript
233export default ->
234 print "hello"
235 123
236```
237<YueDisplay>
238
239```yue
240export default ->
241 print "hello"
242 123
243```
244
245</YueDisplay>
diff --git a/doc/docs/doc/object-oriented-programming.md b/doc/docs/doc/object-oriented-programming.md
new file mode 100644
index 0000000..6a8559e
--- /dev/null
+++ b/doc/docs/doc/object-oriented-programming.md
@@ -0,0 +1,555 @@
1# Object Oriented Programming
2
3In 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.
4
5A simple class:
6
7```yuescript
8class Inventory
9 new: =>
10 @items = {}
11
12 add_item: (name) =>
13 if @items[name]
14 @items[name] += 1
15 else
16 @items[name] = 1
17```
18<YueDisplay>
19
20```yue
21class Inventory
22 new: =>
23 @items = {}
24
25 add_item: (name) =>
26 if @items[name]
27 @items[name] += 1
28 else
29 @items[name] = 1
30```
31
32</YueDisplay>
33
34A class is declared with a class statement followed by a table-like declaration where all of the methods and properties are listed.
35
36The new property is special in that it will become the constructor.
37
38Notice how all the methods in the class use the fat arrow function syntax. When calling methods on a instance, the instance itself is sent in as the first argument. The fat arrow handles the creation of a self argument.
39
40The @ prefix on a variable name is shorthand for self.. @items becomes self.items.
41
42Creating an instance of the class is done by calling the name of the class as a function.
43
44```yuescript
45inv = Inventory!
46inv\add_item "t-shirt"
47inv\add_item "pants"
48```
49<YueDisplay>
50
51```yue
52inv = Inventory!
53inv\add_item "t-shirt"
54inv\add_item "pants"
55```
56
57</YueDisplay>
58
59Because the instance of the class needs to be sent to the methods when they are called, the \ operator is used.
60
61All properties of a class are shared among the instances. This is fine for functions, but for other types of objects, undesired results may occur.
62
63Consider the example below, the clothes property is shared amongst all instances, so modifications to it in one instance will show up in another:
64
65```yuescript
66class Person
67 clothes: []
68 give_item: (name) =>
69 table.insert @clothes, name
70
71a = Person!
72b = Person!
73
74a\give_item "pants"
75b\give_item "shirt"
76
77-- will print both pants and shirt
78print item for item in *a.clothes
79```
80<YueDisplay>
81
82```yue
83class Person
84 clothes: []
85 give_item: (name) =>
86 table.insert @clothes, name
87
88a = Person!
89b = Person!
90
91a\give_item "pants"
92b\give_item "shirt"
93
94-- will print both pants and shirt
95print item for item in *a.clothes
96```
97
98</YueDisplay>
99
100The proper way to avoid this problem is to create the mutable state of the object in the constructor:
101
102```yuescript
103class Person
104 new: =>
105 @clothes = []
106```
107<YueDisplay>
108
109```yue
110class Person
111 new: =>
112 @clothes = []
113```
114
115</YueDisplay>
116
117## Inheritance
118
119The extends keyword can be used in a class declaration to inherit the properties and methods from another class.
120
121```yuescript
122class BackPack extends Inventory
123 size: 10
124 add_item: (name) =>
125 if #@items > size then error "backpack is full"
126 super name
127```
128<YueDisplay>
129
130```yue
131class BackPack extends Inventory
132 size: 10
133 add_item: (name) =>
134 if #@items > size then error "backpack is full"
135 super name
136```
137
138</YueDisplay>
139
140Here we extend our Inventory class, and limit the amount of items it can carry.
141
142In 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.
143
144Whenever 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.
145
146```yuescript
147class Shelf
148 @__inherited: (child) =>
149 print @__name, "was inherited by", child.__name
150
151-- will print: Shelf was inherited by Cupboard
152class Cupboard extends Shelf
153```
154<YueDisplay>
155
156```yue
157class Shelf
158 @__inherited: (child) =>
159 print @__name, "was inherited by", child.__name
160
161-- will print: Shelf was inherited by Cupboard
162class Cupboard extends Shelf
163```
164
165</YueDisplay>
166
167## Super
168
169**super** is a special keyword that can be used in two different ways: It can be treated as an object, or it can be called like a function. It only has special functionality when inside a class.
170
171When called as a function, it will call the function of the same name in the parent class. The current self will automatically be passed as the first argument. (As seen in the inheritance example above)
172
173When super is used as a normal value, it is a reference to the parent class object.
174
175It can be accessed like any of object in order to retrieve values in the parent class that might have been shadowed by the child class.
176
177When the \ calling operator is used with super, self is inserted as the first argument instead of the value of super itself. When using . to retrieve a function, the raw function is returned.
178
179A few examples of using super in different ways:
180
181```yuescript
182class MyClass extends ParentClass
183 a_method: =>
184 -- the following have the same effect:
185 super "hello", "world"
186 super\a_method "hello", "world"
187 super.a_method self, "hello", "world"
188
189 -- super as a value is equal to the parent class:
190 assert super == ParentClass
191```
192<YueDisplay>
193
194```yue
195class MyClass extends ParentClass
196 a_method: =>
197 -- the following have the same effect:
198 super "hello", "world"
199 super\a_method "hello", "world"
200 super.a_method self, "hello", "world"
201
202 -- super as a value is equal to the parent class:
203 assert super == ParentClass
204```
205
206</YueDisplay>
207
208**super** can also be used on left side of a Function Stub. The only major difference is that instead of the resulting function being bound to the value of super, it is bound to self.
209
210## Types
211
212Every instance of a class carries its type with it. This is stored in the special __class property. This property holds the class object. The class object is what we call to build a new instance. We can also index the class object to retrieve class methods and properties.
213
214```yuescript
215b = BackPack!
216assert b.__class == BackPack
217
218print BackPack.size -- prints 10
219```
220<YueDisplay>
221
222```yue
223b = BackPack!
224assert b.__class == BackPack
225
226print BackPack.size -- prints 10
227```
228
229</YueDisplay>
230
231## Class Objects
232
233The 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.
234
235The 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.
236
237A 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.
238
239The 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.
240
241It 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.
242
243The class object has a couple special properties:
244
245The name of the class as when it was declared is stored as a string in the __name field of the class object.
246
247```yuescript
248print BackPack.__name -- prints Backpack
249```
250<YueDisplay>
251
252```yue
253print BackPack.__name -- prints Backpack
254```
255
256</YueDisplay>
257
258The base object is stored in __base. We can modify this table to add functionality to instances that have already been created and ones that are yet to be created.
259
260If the class extends from anything, the parent class object is stored in __parent.
261
262## Class Variables
263
264We can create variables directly in the class object instead of in the base by using @ in the front of the property name in a class declaration.
265
266```yuescript
267class Things
268 @some_func: => print "Hello from", @__name
269
270Things\some_func!
271
272-- class variables not visible in instances
273assert Things().some_func == nil
274```
275<YueDisplay>
276
277```yue
278class Things
279 @some_func: => print "Hello from", @__name
280
281Things\some_func!
282
283-- class variables not visible in instances
284assert Things().some_func == nil
285```
286
287</YueDisplay>
288
289In expressions, we can use @@ to access a value that is stored in the __class of self. Thus, @@hello is shorthand for self.__class.hello.
290
291```yuescript
292class Counter
293 @count: 0
294
295 new: =>
296 @@count += 1
297
298Counter!
299Counter!
300
301print Counter.count -- prints 2
302```
303<YueDisplay>
304
305```yue
306class Counter
307 @count: 0
308
309 new: =>
310 @@count += 1
311
312Counter!
313Counter!
314
315print Counter.count -- prints 2
316```
317
318</YueDisplay>
319
320The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax.
321
322```yuescript
323@@hello 1,2,3,4
324```
325<YueDisplay>
326
327```yue
328@@hello 1,2,3,4
329```
330
331</YueDisplay>
332
333## Class Declaration Statements
334
335In 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.
336
337Here is an alternative way to create a class variable compared to what's described above:
338
339```yuescript
340class Things
341 @class_var = "hello world"
342```
343<YueDisplay>
344
345```yue
346class Things
347 @class_var = "hello world"
348```
349
350</YueDisplay>
351
352These expressions are executed after all the properties have been added to the base.
353
354All variables declared in the body of the class are local to the classes properties. This is convenient for placing private values or helper functions that only the class methods can access:
355
356```yuescript
357class MoreThings
358 secret = 123
359 log = (msg) -> print "LOG:", msg
360
361 some_method: =>
362 log "hello world: " .. secret
363```
364<YueDisplay>
365
366```yue
367class MoreThings
368 secret = 123
369 log = (msg) -> print "LOG:", msg
370
371 some_method: =>
372 log "hello world: " .. secret
373```
374
375</YueDisplay>
376
377## @ and @@ Values
378
379When @ and @@ are prefixed in front of a name they represent, respectively, that name accessed in self and self.__class.
380
381If they are used all by themselves, they are aliases for self and self.__class.
382
383```yuescript
384assert @ == self
385assert @@ == self.__class
386```
387<YueDisplay>
388
389```yue
390assert @ == self
391assert @@ == self.__class
392```
393
394</YueDisplay>
395
396For example, a quick way to create a new instance of the same class from an instance method using @@:
397
398```yuescript
399some_instance_method = (...) => @@ ...
400```
401<YueDisplay>
402
403```yue
404some_instance_method = (...) => @@ ...
405```
406
407</YueDisplay>
408
409## Constructor Property Promotion
410
411To reduce the boilerplate code for definition of simple value objects. You can write a simple class like:
412
413```yuescript
414class Something
415 new: (@foo, @bar, @@biz, @@baz) =>
416
417-- Which is short for
418
419class Something
420 new: (foo, bar, biz, baz) =>
421 @foo = foo
422 @bar = bar
423 @@biz = biz
424 @@baz = baz
425```
426<YueDisplay>
427
428```yue
429class Something
430 new: (@foo, @bar, @@biz, @@baz) =>
431
432-- Which is short for
433
434class Something
435 new: (foo, bar, biz, baz) =>
436 @foo = foo
437 @bar = bar
438 @@biz = biz
439 @@baz = baz
440```
441
442</YueDisplay>
443
444You can also use this syntax for a common function to initialize a object's fields.
445
446```yuescript
447new = (@fieldA, @fieldB) => @
448obj = new {}, 123, "abc"
449print obj
450```
451<YueDisplay>
452
453```yue
454new = (@fieldA, @fieldB) => @
455obj = new {}, 123, "abc"
456print obj
457```
458
459</YueDisplay>
460
461## Class Expressions
462
463The class syntax can also be used as an expression which can be assigned to a variable or explicitly returned.
464
465```yuescript
466x = class Bucket
467 drops: 0
468 add_drop: => @drops += 1
469```
470<YueDisplay>
471
472```yue
473x = class Bucket
474 drops: 0
475 add_drop: => @drops += 1
476```
477
478</YueDisplay>
479
480## Anonymous classes
481
482The name can be left out when declaring a class. The __name attribute will be nil, unless the class expression is in an assignment. The name on the left hand side of the assignment is used instead of nil.
483
484```yuescript
485BigBucket = class extends Bucket
486 add_drop: => @drops += 10
487
488assert Bucket.__name == "BigBucket"
489```
490<YueDisplay>
491
492```yue
493BigBucket = class extends Bucket
494 add_drop: => @drops += 10
495
496assert Bucket.__name == "BigBucket"
497```
498
499</YueDisplay>
500
501You can even leave off the body, meaning you can write a blank anonymous class like this:
502
503```yuescript
504x = class
505```
506<YueDisplay>
507
508```yue
509x = class
510```
511
512</YueDisplay>
513
514## Class Mixing
515
516You can do mixing with keyword `using` to copy functions from either a plain table or a predefined class object into your new class. When doing mixing with a plain table, you can override the class indexing function (metamethod `__index`) to your customized implementation. When doing mixing with an existing class object, the class object's metamethods won't be copied.
517
518```yuescript
519MyIndex = __index: var: 1
520
521class X using MyIndex
522 func: =>
523 print 123
524
525x = X!
526print x.var
527
528class Y using X
529
530y = Y!
531y\func!
532
533assert y.__class.__parent ~= X -- X is not parent of Y
534```
535<YueDisplay>
536
537```yue
538MyIndex = __index: var: 1
539
540class X using MyIndex
541 func: =>
542 print 123
543
544x = X!
545print x.var
546
547class Y using X
548
549y = Y!
550y\func!
551
552assert y.__class.__parent ~= X -- X is not parent of Y
553```
554
555</YueDisplay>
diff --git a/doc/docs/doc/operator.md b/doc/docs/doc/operator.md
new file mode 100644
index 0000000..9a2e89b
--- /dev/null
+++ b/doc/docs/doc/operator.md
@@ -0,0 +1,460 @@
1# Operator
2
3All 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.
4
5```yuescript
6tb\func! if tb ~= nil
7tb::func! if tb != nil
8```
9<YueDisplay>
10
11```yue
12tb\func! if tb ~= nil
13tb::func! if tb != nil
14```
15
16</YueDisplay>
17
18## Chaining Comparisons
19
20Comparisons can be arbitrarily chained:
21
22```yuescript
23print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
24-- output: true
25
26a = 5
27print 1 <= a <= 10
28-- output: true
29```
30<YueDisplay>
31
32```yue
33print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
34-- output: true
35
36a = 5
37print 1 <= a <= 10
38-- output: true
39```
40
41</YueDisplay>
42
43Note the evaluation behavior of chained comparisons:
44
45```yuescript
46v = (x) ->
47 print x
48 x
49
50print v(1) < v(2) <= v(3)
51--[[
52 output:
53 2
54 1
55 3
56 true
57]]
58
59print v(1) > v(2) <= v(3)
60--[[
61 output:
62 2
63 1
64 false
65]]
66```
67<YueDisplay>
68
69```yue
70v = (x) ->
71 print x
72 x
73
74print v(1) < v(2) <= v(3)
75--[[
76 output:
77 2
78 1
79 3
80 true
81]]
82
83print v(1) > v(2) <= v(3)
84--[[
85 output:
86 2
87 1
88 false
89]]
90```
91
92</YueDisplay>
93
94The middle expression is only evaluated once, rather than twice as it would be if the expression were written as `v(1) < v(2) and v(2) <= v(3)`. However, the order of evaluations in a chained comparison is undefined. It is strongly recommended not to use expressions with side effects (such as printing) in chained comparisons. If side effects are required, the short-circuit `and` operator should be used explicitly.
95
96## Table Appending
97
98The **[] =** operator is used to append values to tables.
99
100```yuescript
101tab = []
102tab[] = "Value"
103```
104<YueDisplay>
105
106```yue
107tab = []
108tab[] = "Value"
109```
110
111</YueDisplay>
112
113You can also use the spread operator `...` to append all elements from one list to another:
114
115```yuescript
116tbA = [1, 2, 3]
117tbB = [4, 5, 6]
118tbA[] = ...tbB
119-- tbA is now [1, 2, 3, 4, 5, 6]
120```
121<YueDisplay>
122
123```yue
124tbA = [1, 2, 3]
125tbB = [4, 5, 6]
126tbA[] = ...tbB
127-- tbA is now [1, 2, 3, 4, 5, 6]
128```
129
130</YueDisplay>
131
132## Table Spreading
133
134You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals.
135
136```yuescript
137parts =
138 * "shoulders"
139 * "knees"
140lyrics =
141 * "head"
142 * ...parts
143 * "and"
144 * "toes"
145
146copy = {...other}
147
148a = {1, 2, 3, x: 1}
149b = {4, 5, y: 1}
150merge = {...a, ...b}
151```
152<YueDisplay>
153
154```yue
155parts =
156 * "shoulders"
157 * "knees"
158lyrics =
159 * "head"
160 * ...parts
161 * "and"
162 * "toes"
163
164copy = {...other}
165
166a = {1, 2, 3, x: 1}
167b = {4, 5, y: 1}
168merge = {...a, ...b}
169```
170
171</YueDisplay>
172
173## Table Reversed Indexing
174
175You can use the **#** operator to get the last elements of a table.
176
177```yuescript
178last = data.items[#]
179second_last = data.items[#-1]
180data.items[#] = 1
181```
182<YueDisplay>
183
184```yue
185last = data.items[#]
186second_last = data.items[#-1]
187data.items[#] = 1
188```
189
190</YueDisplay>
191
192## Metatable
193
194The **<>** operator can be used as a shortcut for metatable manipulation.
195
196### Metatable Creation
197
198Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**.
199
200```yuescript
201mt = {}
202add = (right) => <>: mt, value: @value + right.value
203mt.__add = add
204
205a = <>: mt, value: 1
206 -- set field with variable of the same name
207b = :<add>, value: 2
208c = <add>: mt.__add, value: 3
209
210d = a + b + c
211print d.value
212
213close _ = <close>: -> print "out of scope"
214```
215<YueDisplay>
216
217```yue
218mt = {}
219add = (right) => <>: mt, value: @value + right.value
220mt.__add = add
221
222a = <>: mt, value: 1
223 -- set field with variable of the same name
224b = :<add>, value: 2
225c = <add>: mt.__add, value: 3
226
227d = a + b + c
228print d.value
229
230close _ = <close>: -> print "out of scope"
231```
232
233</YueDisplay>
234
235### Metatable Accessing
236
237Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**.
238
239```yuescript
240-- create with metatable containing field "value"
241tb = <"value">: 123
242tb.<index> = tb.<>
243print tb.value
244
245tb.<> = __index: {item: "hello"}
246print tb.item
247```
248<YueDisplay>
249
250```yue
251-- create with metatable containing field "value"
252tb = <"value">: 123
253tb.<index> = tb.<>
254print tb.value
255tb.<> = __index: {item: "hello"}
256print tb.item
257```
258
259</YueDisplay>
260
261### Metatable Destructure
262
263Destruct metatable with metamethod key surrounded by **<>**.
264
265```yuescript
266{item, :new, :<close>, <index>: getter} = tb
267print item, new, close, getter
268```
269<YueDisplay>
270
271```yue
272{item, :new, :<close>, <index>: getter} = tb
273print item, new, close, getter
274```
275
276</YueDisplay>
277
278## Existence
279
280The **?** operator can be used in a variety of contexts to check for existence.
281
282```yuescript
283func?!
284print abc?["hello world"]?.xyz
285
286x = tab?.value
287len = utf8?.len or string?.len or (o) -> #o
288
289if print and x?
290 print x
291
292with? io.open "test.txt", "w"
293 \write "hello"
294 \close!
295```
296<YueDisplay>
297
298```yue
299func?!
300print abc?["hello world"]?.xyz
301
302x = tab?.value
303len = utf8?.len or string?.len or (o) -> #o
304
305if print and x?
306 print x
307
308with? io.open "test.txt", "w"
309 \write "hello"
310 \close!
311```
312
313</YueDisplay>
314
315## Piping
316
317Instead of a series of nested function calls, you can pipe values with operator **|>**.
318
319```yuescript
320"hello" |> print
3211 |> print 2 -- insert pipe item as the first argument
3222 |> print 1, _, 3 -- pipe with a placeholder
323
324-- pipe expression in multiline
325readFile "example.txt"
326 |> extract language, {}
327 |> parse language
328 |> emit
329 |> render
330 |> print
331```
332<YueDisplay>
333
334```yue
335"hello" |> print
3361 |> print 2 -- insert pipe item as the first argument
3372 |> print 1, _, 3 -- pipe with a placeholder
338-- pipe expression in multiline
339readFile "example.txt"
340 |> extract language, {}
341 |> parse language
342 |> emit
343 |> render
344 |> print
345```
346
347</YueDisplay>
348
349## Nil Coalescing
350
351The nil-coalescing operator **??** returns the value of its left-hand operand if it isn't **nil**; otherwise, it evaluates the right-hand operand and returns its result. The **??** operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-nil.
352```yuescript
353local a, b, c, d
354a = b ?? c ?? d
355func a ?? {}
356
357a ??= false
358```
359<YueDisplay>
360
361```yue
362local a, b, c, d
363a = b ?? c ?? d
364func a ?? {}
365a ??= false
366```
367
368</YueDisplay>
369
370## Implicit Object
371
372You 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.
373
374```yuescript
375-- assignment with implicit object
376list =
377 * 1
378 * 2
379 * 3
380
381-- function call with implicit object
382func
383 * 1
384 * 2
385 * 3
386
387-- return with implicit object
388f = ->
389 return
390 * 1
391 * 2
392 * 3
393
394-- table with implicit object
395tb =
396 name: "abc"
397
398 values:
399 - "a"
400 - "b"
401 - "c"
402
403 objects:
404 - name: "a"
405 value: 1
406 func: => @value + 1
407 tb:
408 fieldA: 1
409
410 - name: "b"
411 value: 2
412 func: => @value + 2
413 tb: { }
414
415```
416<YueDisplay>
417
418```yue
419-- assignment with implicit object
420list =
421 * 1
422 * 2
423 * 3
424
425-- function call with implicit object
426func
427 * 1
428 * 2
429 * 3
430
431-- return with implicit object
432f = ->
433 return
434 * 1
435 * 2
436 * 3
437
438-- table with implicit object
439tb =
440 name: "abc"
441
442 values:
443 - "a"
444 - "b"
445 - "c"
446
447 objects:
448 - name: "a"
449 value: 1
450 func: => @value + 1
451 tb:
452 fieldA: 1
453
454 - name: "b"
455 value: 2
456 func: => @value + 2
457 tb: { }
458```
459
460</YueDisplay>
diff --git a/doc/docs/doc/switch.md b/doc/docs/doc/switch.md
new file mode 100644
index 0000000..f503a80
--- /dev/null
+++ b/doc/docs/doc/switch.md
@@ -0,0 +1,296 @@
1# Switch
2
3The 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.
4
5```yuescript
6switch name := "Dan"
7 when "Robert"
8 print "You are Robert"
9 when "Dan", "Daniel"
10 print "Your name, it's Dan"
11 else
12 print "I don't know about you with name #{name}"
13```
14<YueDisplay>
15
16```yue
17switch name := "Dan"
18 when "Robert"
19 print "You are Robert"
20 when "Dan", "Daniel"
21 print "Your name, it's Dan"
22 else
23 print "I don't know about you with name #{name}"
24```
25
26</YueDisplay>
27
28A switch when clause can match against multiple values by listing them out comma separated.
29
30Switches can be used as expressions as well, here we can assign the result of the switch to a variable:
31
32```yuescript
33b = 1
34next_number = switch b
35 when 1
36 2
37 when 2
38 3
39 else
40 error "can't count that high!"
41```
42<YueDisplay>
43
44```yue
45b = 1
46next_number = switch b
47 when 1
48 2
49 when 2
50 3
51 else
52 error "can't count that high!"
53```
54
55</YueDisplay>
56
57We 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.
58
59```yuescript
60msg = switch math.random(1, 5)
61 when 1 then "you are lucky"
62 when 2 then "you are almost lucky"
63 else "not so lucky"
64```
65<YueDisplay>
66
67```yue
68msg = switch math.random(1, 5)
69 when 1 then "you are lucky"
70 when 2 then "you are almost lucky"
71 else "not so lucky"
72```
73
74</YueDisplay>
75
76If you want to write code with one less indent when writing a switch statement, you can put the first when clause on the statement start line, and then all other clauses can be written with one less indent.
77
78```yuescript
79switch math.random(1, 5)
80 when 1
81 print "you are lucky" -- two indents
82 else
83 print "not so lucky"
84
85switch math.random(1, 5) when 1
86 print "you are lucky" -- one indent
87else
88 print "not so lucky"
89```
90<YueDisplay>
91
92```yue
93switch math.random(1, 5)
94 when 1
95 print "you are lucky" -- two indents
96 else
97 print "not so lucky"
98
99switch math.random(1, 5) when 1
100 print "you are lucky" -- one indent
101else
102 print "not so lucky"
103```
104
105</YueDisplay>
106
107It 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.
108
109## Table Matching
110
111You can do table matching in a switch when clause, if the table can be destructured by a specific structure and get non-nil values.
112
113```yuescript
114items =
115 * x: 100
116 y: 200
117 * width: 300
118 height: 400
119
120for item in *items
121 switch item
122 when :x, :y
123 print "Vec2 #{x}, #{y}"
124 when :width, :height
125 print "size #{width}, #{height}"
126```
127<YueDisplay>
128
129```yue
130items =
131 * x: 100
132 y: 200
133 * width: 300
134 height: 400
135
136for item in *items
137 switch item
138 when :x, :y
139 print "Vec2 #{x}, #{y}"
140 when :width, :height
141 print "size #{width}, #{height}"
142```
143
144</YueDisplay>
145
146You can use default values to optionally destructure the table for some fields.
147
148```yuescript
149item = {}
150
151{pos: {:x = 50, :y = 200}} = item -- get error: attempt to index a nil value (field 'pos')
152
153switch item
154 when {pos: {:x = 50, :y = 200}}
155 print "Vec2 #{x}, #{y}" -- table destructuring will still pass
156```
157<YueDisplay>
158
159```yue
160item = {}
161
162{pos: {:x = 50, :y = 200}} = item -- get error: attempt to index a nil value (field 'pos')
163
164switch item
165 when {pos: {:x = 50, :y = 200}}
166 print "Vec2 #{x}, #{y}" -- table destructuring will still pass
167```
168
169</YueDisplay>
170
171You can also match against array elements, table fields, and even nested structures with array or table literals.
172
173Match against array elements.
174
175```yuescript
176switch tb
177 when [1, 2, 3]
178 print "1, 2, 3"
179 when [1, b, 3]
180 print "1, #{b}, 3"
181 when [1, 2, b = 3] -- b has a default value
182 print "1, 2, #{b}"
183```
184<YueDisplay>
185
186```yue
187switch tb
188 when [1, 2, 3]
189 print "1, 2, 3"
190 when [1, b, 3]
191 print "1, #{b}, 3"
192 when [1, 2, b = 3] -- b has a default value
193 print "1, 2, #{b}"
194```
195
196</YueDisplay>
197
198Match against table fields with destructuring.
199
200```yuescript
201switch tb
202 when success: true, :result
203 print "success", result
204 when success: false
205 print "failed", result
206 else
207 print "invalid"
208```
209<YueDisplay>
210
211```yue
212switch tb
213 when success: true, :result
214 print "success", result
215 when success: false
216 print "failed", result
217 else
218 print "invalid"
219```
220
221</YueDisplay>
222
223Match against nested table structures.
224
225```yuescript
226switch tb
227 when data: {type: "success", :content}
228 print "success", content
229 when data: {type: "error", :content}
230 print "failed", content
231 else
232 print "invalid"
233```
234<YueDisplay>
235
236```yue
237switch tb
238 when data: {type: "success", :content}
239 print "success", content
240 when data: {type: "error", :content}
241 print "failed", content
242 else
243 print "invalid"
244```
245
246</YueDisplay>
247
248Match against array of tables.
249
250```yuescript
251switch tb
252 when [
253 {a: 1, b: 2}
254 {a: 3, b: 4}
255 {a: 5, b: 6}
256 fourth
257 ]
258 print "matched", fourth
259```
260<YueDisplay>
261
262```yue
263switch tb
264 when [
265 {a: 1, b: 2}
266 {a: 3, b: 4}
267 {a: 5, b: 6}
268 fourth
269 ]
270 print "matched", fourth
271```
272
273</YueDisplay>
274
275Match against a list and capture a range of elements.
276
277```yuescript
278segments = ["admin", "users", "logs", "view"]
279switch segments
280 when [...groups, resource, action]
281 print "Group:", groups -- prints: {"admin", "users"}
282 print "Resource:", resource -- prints: "logs"
283 print "Action:", action -- prints: "view"
284```
285<YueDisplay>
286
287```yue
288segments = ["admin", "users", "logs", "view"]
289switch segments
290 when [...groups, resource, action]
291 print "Group:", groups -- prints: {"admin", "users"}
292 print "Resource:", resource -- prints: "logs"
293 print "Action:", action -- prints: "view"
294```
295
296</YueDisplay>
diff --git a/doc/docs/doc/table-literals.md b/doc/docs/doc/table-literals.md
new file mode 100644
index 0000000..c1adcab
--- /dev/null
+++ b/doc/docs/doc/table-literals.md
@@ -0,0 +1,168 @@
1# Table Literals
2
3Like in Lua, tables are delimited in curly braces.
4
5```yuescript
6some_values = [1, 2, 3, 4]
7```
8<YueDisplay>
9
10```yue
11some_values = [1, 2, 3, 4]
12```
13
14</YueDisplay>
15
16Unlike Lua, assigning a value to a key in a table is done with **:** (instead of **=**).
17
18```yuescript
19some_values = {
20 name: "Bill",
21 age: 200,
22 ["favorite food"]: "rice"
23}
24```
25<YueDisplay>
26
27```yue
28some_values = {
29 name: "Bill",
30 age: 200,
31 ["favorite food"]: "rice"
32}
33```
34
35</YueDisplay>
36
37The curly braces can be left off if a single table of key value pairs is being assigned.
38
39```yuescript
40profile =
41 height: "4 feet",
42 shoe_size: 13,
43 favorite_foods: ["ice cream", "donuts"]
44```
45<YueDisplay>
46
47```yue
48profile =
49 height: "4 feet",
50 shoe_size: 13,
51 favorite_foods: ["ice cream", "donuts"]
52```
53
54</YueDisplay>
55
56Newlines can be used to delimit values instead of a comma (or both):
57
58```yuescript
59values = {
60 1, 2, 3, 4
61 5, 6, 7, 8
62 name: "superman"
63 occupation: "crime fighting"
64}
65```
66<YueDisplay>
67
68```yue
69values = {
70 1, 2, 3, 4
71 5, 6, 7, 8
72 name: "superman"
73 occupation: "crime fighting"
74}
75```
76
77</YueDisplay>
78
79When creating a single line table literal, the curly braces can also be left off:
80
81```yuescript
82my_function dance: "Tango", partner: "none"
83
84y = type: "dog", legs: 4, tails: 1
85```
86<YueDisplay>
87
88```yue
89my_function dance: "Tango", partner: "none"
90
91y = type: "dog", legs: 4, tails: 1
92```
93
94</YueDisplay>
95
96The keys of a table literal can be language keywords without being escaped:
97
98```yuescript
99tbl = {
100 do: "something"
101 end: "hunger"
102}
103```
104<YueDisplay>
105
106```yue
107tbl = {
108 do: "something"
109 end: "hunger"
110}
111```
112
113</YueDisplay>
114
115If you are constructing a table out of variables and wish the keys to be the same as the variable names, then the **:** prefix operator can be used:
116
117```yuescript
118hair = "golden"
119height = 200
120person = { :hair, :height, shoe_size: 40 }
121
122print_table :hair, :height
123```
124<YueDisplay>
125
126```yue
127hair = "golden"
128height = 200
129person = { :hair, :height, shoe_size: 40 }
130
131print_table :hair, :height
132```
133
134</YueDisplay>
135
136If you want the key of a field in the table to to be result of an expression, then you can wrap it in **[ ]**, just like in Lua. You can also use a string literal directly as a key, leaving out the square brackets. This is useful if your key has any special characters.
137
138```yuescript
139t = {
140 [1 + 2]: "hello"
141 "hello world": true
142}
143```
144<YueDisplay>
145
146```yue
147t = {
148 [1 + 2]: "hello"
149 "hello world": true
150}
151```
152
153</YueDisplay>
154
155Lua tables have both an array part and a hash part, but sometimes you want to make a semantic distinction between array and hash usage when writing Lua tables. Then you can write Lua table with **[ ]** instead of **{ }** to represent an array table and writing any key value pair in a list table won't be allowed.
156
157```yuescript
158some_values = [1, 2, 3, 4]
159list_with_one_element = [1, ]
160```
161<YueDisplay>
162
163```yue
164some_values = [1, 2, 3, 4]
165list_with_one_element = [1, ]
166```
167
168</YueDisplay>
diff --git a/doc/docs/doc/the-using-clause-controlling-destructive-assignment.md b/doc/docs/doc/the-using-clause-controlling-destructive-assignment.md
new file mode 100644
index 0000000..fb9b740
--- /dev/null
+++ b/doc/docs/doc/the-using-clause-controlling-destructive-assignment.md
@@ -0,0 +1,98 @@
1# The Using Clause; Controlling Destructive Assignment
2
3While lexical scoping can be a great help in reducing the complexity of the code we write, things can get unwieldy as the code size increases. Consider the following snippet:
4
5```yuescript
6i = 100
7
8-- many lines of code...
9
10my_func = ->
11 i = 10
12 while i > 0
13 print i
14 i -= 1
15
16my_func!
17
18print i -- will print 0
19```
20<YueDisplay>
21
22```yue
23i = 100
24
25-- many lines of code...
26
27my_func = ->
28 i = 10
29 while i > 0
30 print i
31 i -= 1
32
33my_func!
34
35print i -- will print 0
36```
37
38</YueDisplay>
39
40In 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.
41
42It 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.
43
44The using keyword lets us do that. using nil makes sure that no closed variables are overwritten in assignment. The using clause is placed after the argument list in a function, or in place of it if there are no arguments.
45
46```yuescript
47i = 100
48
49my_func = (using nil) ->
50 i = "hello" -- a new local variable is created here
51
52my_func!
53print i -- prints 100, i is unaffected
54```
55<YueDisplay>
56
57```yue
58i = 100
59
60my_func = (using nil) ->
61 i = "hello" -- a new local variable is created here
62
63my_func!
64print i -- prints 100, i is unaffected
65```
66
67</YueDisplay>
68
69Multiple names can be separated by commas. Closure values can still be accessed, they just cant be modified:
70
71```yuescript
72tmp = 1213
73i, k = 100, 50
74
75my_func = (add using k, i) ->
76 tmp = tmp + add -- a new local tmp is created
77 i += tmp
78 k += tmp
79
80my_func(22)
81print i, k -- these have been updated
82```
83<YueDisplay>
84
85```yue
86tmp = 1213
87i, k = 100, 50
88
89my_func = (add using k, i) ->
90 tmp = tmp + add -- a new local tmp is created
91 i += tmp
92 k += tmp
93
94my_func(22)
95print i, k -- these have been updated
96```
97
98</YueDisplay>
diff --git a/doc/docs/doc/the-yuescript-library.md b/doc/docs/doc/the-yuescript-library.md
new file mode 100644
index 0000000..3761755
--- /dev/null
+++ b/doc/docs/doc/the-yuescript-library.md
@@ -0,0 +1,821 @@
1# The YueScript Library
2
3Access it by `local yue = require("yue")` in Lua.
4
5## yue
6
7**Description:**
8
9The YueScript language library.
10
11### version
12
13**Type:** Field.
14
15**Description:**
16
17The YueScript version.
18
19**Signature:**
20```lua
21version: string
22```
23
24### dirsep
25
26**Type:** Field.
27
28**Description:**
29
30The file separator for the current platform.
31
32**Signature:**
33```lua
34dirsep: string
35```
36
37### yue_compiled
38
39**Type:** Field.
40
41**Description:**
42
43The compiled module code cache.
44
45**Signature:**
46```lua
47yue_compiled: {string: string}
48```
49
50### to_lua
51
52**Type:** Function.
53
54**Description:**
55
56The YueScript compiling function. It compiles the YueScript code to Lua code.
57
58**Signature:**
59```lua
60to_lua: function(code: string, config?: Config):
61 --[[codes]] string | nil,
62 --[[error]] string | nil,
63 --[[globals]] {{string, integer, integer}} | nil
64```
65
66**Parameters:**
67
68| Parameter | Type | Description |
69| --- | --- | --- |
70| code | string | The YueScript code. |
71| config | Config | [Optional] The compiler options. |
72
73**Returns:**
74
75| Return Type | Description |
76| --- | --- |
77| string \| nil | The compiled Lua code, or nil if the compilation failed. |
78| string \| nil | The error message, or nil if the compilation succeeded. |
79| {{string, integer, integer}} \| nil | The global variables appearing in the code (with name, row and column), or nil if the compiler option `lint_global` is false. |
80
81### file_exist
82
83**Type:** Function.
84
85**Description:**
86
87The source file existence checking function. Can be overridden to customize the behavior.
88
89**Signature:**
90```lua
91file_exist: function(filename: string): boolean
92```
93
94**Parameters:**
95
96| Parameter | Type | Description |
97| --- | --- | --- |
98| filename | string | The file name. |
99
100**Returns:**
101
102| Return Type | Description |
103| --- | --- |
104| boolean | Whether the file exists. |
105
106### read_file
107
108**Type:** Function.
109
110**Description:**
111
112The source file reading function. Can be overridden to customize the behavior.
113
114**Signature:**
115```lua
116read_file: function(filename: string): string
117```
118
119**Parameters:**
120
121| Parameter | Type | Description |
122| --- | --- | --- |
123| filename | string | The file name. |
124
125**Returns:**
126
127| Return Type | Description |
128| --- | --- |
129| string | The file content. |
130
131### insert_loader
132
133**Type:** Function.
134
135**Description:**
136
137Insert the YueScript loader to the package loaders (searchers).
138
139**Signature:**
140```lua
141insert_loader: function(pos?: integer): boolean
142```
143
144**Parameters:**
145
146| Parameter | Type | Description |
147| --- | --- | --- |
148| pos | integer | [Optional] The position to insert the loader. Default is 3. |
149
150**Returns:**
151
152| Return Type | Description |
153| --- | --- |
154| boolean | Whether the loader is inserted successfully. It will fail if the loader is already inserted. |
155
156### remove_loader
157
158**Type:** Function.
159
160**Description:**
161
162Remove the YueScript loader from the package loaders (searchers).
163
164**Signature:**
165```lua
166remove_loader: function(): boolean
167```
168
169**Returns:**
170
171| Return Type | Description |
172| --- | --- |
173| boolean | Whether the loader is removed successfully. It will fail if the loader is not inserted. |
174
175### loadstring
176
177**Type:** Function.
178
179**Description:**
180
181Loads YueScript code from a string into a function.
182
183**Signature:**
184```lua
185loadstring: function(input: string, chunkname: string, env: table, config?: Config):
186 --[[loaded function]] nil | function(...: any): (any...),
187 --[[error]] string | nil
188```
189
190**Parameters:**
191
192| Parameter | Type | Description |
193| --- | --- | --- |
194| input | string | The YueScript code. |
195| chunkname | string | The name of the code chunk. |
196| env | table | The environment table. |
197| config | Config | [Optional] The compiler options. |
198
199**Returns:**
200
201| Return Type | Description |
202| --- | --- |
203| function \| nil | The loaded function, or nil if the loading failed. |
204| string \| nil | The error message, or nil if the loading succeeded. |
205
206### loadstring
207
208**Type:** Function.
209
210**Description:**
211
212Loads YueScript code from a string into a function.
213
214**Signature:**
215```lua
216loadstring: function(input: string, chunkname: string, config?: Config):
217 --[[loaded function]] nil | function(...: any): (any...),
218 --[[error]] string | nil
219```
220
221**Parameters:**
222
223| Parameter | Type | Description |
224| --- | --- | --- |
225| input | string | The YueScript code. |
226| chunkname | string | The name of the code chunk. |
227| config | Config | [Optional] The compiler options. |
228
229**Returns:**
230
231| Return Type | Description |
232| --- | --- |
233| function \| nil | The loaded function, or nil if the loading failed. |
234| string \| nil | The error message, or nil if the loading succeeded. |
235
236### loadstring
237
238**Type:** Function.
239
240**Description:**
241
242Loads YueScript code from a string into a function.
243
244**Signature:**
245```lua
246loadstring: function(input: string, config?: Config):
247 --[[loaded function]] nil | function(...: any): (any...),
248 --[[error]] string | nil
249```
250
251**Parameters:**
252
253| Parameter | Type | Description |
254| --- | --- | --- |
255| input | string | The YueScript code. |
256| config | Config | [Optional] The compiler options. |
257
258**Returns:**
259
260| Return Type | Description |
261| --- | --- |
262| function \| nil | The loaded function, or nil if the loading failed. |
263| string \| nil | The error message, or nil if the loading succeeded. |
264
265### loadfile
266
267**Type:** Function.
268
269**Description:**
270
271Loads YueScript code from a file into a function.
272
273**Signature:**
274```lua
275loadfile: function(filename: string, env: table, config?: Config):
276 nil | function(...: any): (any...),
277 string | nil
278```
279
280**Parameters:**
281
282| Parameter | Type | Description |
283| --- | --- | --- |
284| filename | string | The file name. |
285| env | table | The environment table. |
286| config | Config | [Optional] The compiler options. |
287
288**Returns:**
289
290| Return Type | Description |
291| --- | --- |
292| function \| nil | The loaded function, or nil if the loading failed. |
293| string \| nil | The error message, or nil if the loading succeeded. |
294
295### loadfile
296
297**Type:** Function.
298
299**Description:**
300
301Loads YueScript code from a file into a function.
302
303**Signature:**
304```lua
305loadfile: function(filename: string, config?: Config):
306 nil | function(...: any): (any...),
307 string | nil
308```
309
310**Parameters:**
311
312| Parameter | Type | Description |
313| --- | --- | --- |
314| filename | string | The file name. |
315| config | Config | [Optional] The compiler options. |
316
317**Returns:**
318
319| Return Type | Description |
320| --- | --- |
321| function \| nil | The loaded function, or nil if the loading failed. |
322| string \| nil | The error message, or nil if the loading succeeded. |
323
324### dofile
325
326**Type:** Function.
327
328**Description:**
329
330Loads YueScript code from a file into a function and executes it.
331
332**Signature:**
333```lua
334dofile: function(filename: string, env: table, config?: Config): any...
335```
336
337**Parameters:**
338
339| Parameter | Type | Description |
340| --- | --- | --- |
341| filename | string | The file name. |
342| env | table | The environment table. |
343| config | Config | [Optional] The compiler options. |
344
345**Returns:**
346
347| Return Type | Description |
348| --- | --- |
349| any... | The return values of the loaded function. |
350
351### dofile
352
353**Type:** Function.
354
355**Description:**
356
357Loads YueScript code from a file into a function and executes it.
358
359**Signature:**
360```lua
361dofile: function(filename: string, config?: Config): any...
362```
363
364**Parameters:**
365
366| Parameter | Type | Description |
367| --- | --- | --- |
368| filename | string | The file name. |
369| config | Config | [Optional] The compiler options. |
370
371**Returns:**
372
373| Return Type | Description |
374| --- | --- |
375| any... | The return values of the loaded function. |
376
377### find_modulepath
378
379**Type:** Function.
380
381**Description:**
382
383Resolves the YueScript module name to the file path.
384
385**Signature:**
386```lua
387find_modulepath: function(name: string): string
388```
389
390**Parameters:**
391
392| Parameter | Type | Description |
393| --- | --- | --- |
394| name | string | The module name. |
395
396**Returns:**
397
398| Return Type | Description |
399| --- | --- |
400| string | The file path. |
401
402### pcall
403
404**Type:** Function.
405
406**Description:**
407
408Calls a function in protected mode.
409Catches any errors and returns a status code and results or error object.
410Rewrites the error line number to the original line number in the YueScript code when errors occur.
411
412**Signature:**
413```lua
414pcall: function(f: function, ...: any): boolean, any...
415```
416
417**Parameters:**
418
419| Parameter | Type | Description |
420| --- | --- | --- |
421| f | function | The function to call. |
422| ... | any | Arguments to pass to the function. |
423
424**Returns:**
425
426| Return Type | Description |
427| --- | --- |
428| boolean, ... | Status code and function results or error object. |
429
430### require
431
432**Type:** Function.
433
434**Description:**
435
436Loads a given module. Can be either a Lua module or a YueScript module.
437Rewrites the error line number to the original line number in the YueScript code if the module is a YueScript module and loading fails.
438
439**Signature:**
440```lua
441require: function(name: string): any...
442```
443
444**Parameters:**
445
446| Parameter | Type | Description |
447| --- | --- | --- |
448| modname | string | The name of the module to load. |
449
450**Returns:**
451
452| Return Type | Description |
453| --- | --- |
454| any | The value stored at package.loaded[modname] if the module is already loaded.Otherwise, tries to find a loader and returns the final value of package.loaded[modname] and a loader data as a second result. |
455
456### p
457
458**Type:** Function.
459
460**Description:**
461
462Inspects the structures of the passed values and prints string representations.
463
464**Signature:**
465```lua
466p: function(...: any)
467```
468
469**Parameters:**
470
471| Parameter | Type | Description |
472| --- | --- | --- |
473| ... | any | The values to inspect. |
474
475### options
476
477**Type:** Field.
478
479**Description:**
480
481The current compiler options.
482
483**Signature:**
484```lua
485options: Config.Options
486```
487
488### traceback
489
490**Type:** Function.
491
492**Description:**
493
494The traceback function that rewrites the stack trace line numbers to the original line numbers in the YueScript code.
495
496**Signature:**
497```lua
498traceback: function(message: string): string
499```
500
501**Parameters:**
502
503| Parameter | Type | Description |
504| --- | --- | --- |
505| message | string | The traceback message. |
506
507**Returns:**
508
509| Return Type | Description |
510| --- | --- |
511| string | The rewritten traceback message. |
512
513### is_ast
514
515**Type:** Function.
516
517**Description:**
518
519Checks whether the code matches the specified AST.
520
521**Signature:**
522```lua
523is_ast: function(astName: string, code: string): boolean
524```
525
526**Parameters:**
527
528| Parameter | Type | Description |
529| --- | --- | --- |
530| astName | string | The AST name. |
531| code | string | The code. |
532
533**Returns:**
534
535| Return Type | Description |
536| --- | --- |
537| boolean | Whether the code matches the AST. |
538
539### AST
540
541**Type:** Field.
542
543**Description:**
544
545The AST type definition with name, row, column and sub nodes.
546
547**Signature:**
548```lua
549type AST = {string, integer, integer, any}
550```
551
552### to_ast
553
554**Type:** Function.
555
556**Description:**
557
558Converts the code to the AST.
559
560**Signature:**
561```lua
562to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean):
563 --[[AST]] AST | nil,
564 --[[error]] nil | string
565```
566
567**Parameters:**
568
569| Parameter | Type | Description |
570| --- | --- | --- |
571| code | string | The code. |
572| flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. |
573| astName | string | [Optional] The AST name. Default is "File". |
574| reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is false. |
575
576**Returns:**
577
578| Return Type | Description |
579| --- | --- |
580| AST \| nil | The AST, or nil if the conversion failed. |
581| string \| nil | The error message, or nil if the conversion succeeded. |
582
583### format
584
585**Type:** Function.
586
587**Description:**
588
589Formats the YueScript code.
590
591**Signature:**
592```lua
593format: function(code: string, tabSize?: number, reserveComment?: boolean): string
594```
595
596**Parameters:**
597
598| Parameter | Type | Description |
599| --- | --- | --- |
600| code | string | The code. |
601| tabSize | integer | [Optional] The tab size. Default is 4. |
602| reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is true. |
603
604**Returns:**
605
606| Return Type | Description |
607| --- | --- |
608| string | The formatted code. |
609
610### __call
611
612**Type:** Metamethod.
613
614**Description:**
615
616Requires the YueScript module.
617Rewrites the error line number to the original line number in the YueScript code when loading fails.
618
619**Signature:**
620```lua
621metamethod __call: function(self: yue, module: string): any...
622```
623
624**Parameters:**
625
626| Parameter | Type | Description |
627| --- | --- | --- |
628| module | string | The module name. |
629
630**Returns:**
631
632| Return Type | Description |
633| --- | --- |
634| any | The module value. |
635
636## Config
637
638**Description:**
639
640The compiler compile options.
641
642### lint_global
643
644**Type:** Field.
645
646**Description:**
647
648Whether the compiler should collect the global variables appearing in the code.
649
650**Signature:**
651```lua
652lint_global: boolean
653```
654
655### implicit_return_root
656
657**Type:** Field.
658
659**Description:**
660
661Whether the compiler should do an implicit return for the root code block.
662
663**Signature:**
664```lua
665implicit_return_root: boolean
666```
667
668### reserve_line_number
669
670**Type:** Field.
671
672**Description:**
673
674Whether the compiler should reserve the original line number in the compiled code.
675
676**Signature:**
677```lua
678reserve_line_number: boolean
679```
680
681### reserve_comment
682
683**Type:** Field.
684
685**Description:**
686
687Whether the compiler should reserve the original comments in the compiled code.
688
689**Signature:**
690```lua
691reserve_comment: boolean
692```
693
694### space_over_tab
695
696**Type:** Field.
697
698**Description:**
699
700Whether the compiler should use the space character instead of the tab character in the compiled code.
701
702**Signature:**
703```lua
704space_over_tab: boolean
705```
706
707### same_module
708
709**Type:** Field.
710
711**Description:**
712
713Whether the compiler should treat the code to be compiled as the same currently being compiled module. For internal use only.
714
715**Signature:**
716```lua
717same_module: boolean
718```
719
720### line_offset
721
722**Type:** Field.
723
724**Description:**
725
726Whether the compiler error message should include the line number offset. For internal use only.
727
728**Signature:**
729```lua
730line_offset: integer
731```
732
733### yue.Config.LuaTarget
734
735**Type:** Enumeration.
736
737**Description:**
738
739The target Lua version enumeration.
740
741**Signature:**
742```lua
743enum LuaTarget
744 "5.1"
745 "5.2"
746 "5.3"
747 "5.4"
748 "5.5"
749end
750```
751
752### options
753
754**Type:** Field.
755
756**Description:**
757
758The extra options to be passed to the compilation function.
759
760**Signature:**
761```lua
762options: Options
763```
764
765## Options
766
767**Description:**
768
769The extra compiler options definition.
770
771### target
772
773**Type:** Field.
774
775**Description:**
776
777The target Lua version for the compilation.
778
779**Signature:**
780```lua
781target: LuaTarget
782```
783
784### path
785
786**Type:** Field.
787
788**Description:**
789
790The extra module search path.
791
792**Signature:**
793```lua
794path: string
795```
796
797### dump_locals
798
799**Type:** Field.
800
801**Description:**
802
803Whether to dump the local variables in the traceback error message. Default is false.
804
805**Signature:**
806```lua
807dump_locals: boolean
808```
809
810### simplified
811
812**Type:** Field.
813
814**Description:**
815
816Whether to simplify the error message. Default is true.
817
818**Signature:**
819```lua
820simplified: boolean
821```
diff --git a/doc/docs/doc/try.md b/doc/docs/doc/try.md
new file mode 100644
index 0000000..23c7877
--- /dev/null
+++ b/doc/docs/doc/try.md
@@ -0,0 +1,105 @@
1# Try
2
3The syntax for Lua error handling in a common form.
4
5```yuescript
6try
7 func 1, 2, 3
8catch err
9 print yue.traceback err
10
11success, result = try
12 func 1, 2, 3
13catch err
14 yue.traceback err
15
16try func 1, 2, 3
17catch err
18 print yue.traceback err
19
20success, result = try func 1, 2, 3
21
22try
23 print "trying"
24 func 1, 2, 3
25
26-- working with if assignment pattern
27if success, result := try func 1, 2, 3
28catch err
29 print yue.traceback err
30 print result
31```
32<YueDisplay>
33
34```yue
35try
36 func 1, 2, 3
37catch err
38 print yue.traceback err
39
40success, result = try
41 func 1, 2, 3
42catch err
43 yue.traceback err
44
45try func 1, 2, 3
46catch err
47 print yue.traceback err
48
49success, result = try func 1, 2, 3
50
51try
52 print "trying"
53 func 1, 2, 3
54
55-- working with if assignment pattern
56if success, result := try func 1, 2, 3
57catch err
58 print yue.traceback err
59 print result
60```
61
62</YueDisplay>
63
64## Try?
65
66`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.
67
68```yuescript
69a, b, c = try? func!
70
71-- with nil coalescing operator
72a = (try? func!) ?? "default"
73
74-- as function argument
75f try? func!
76
77-- with catch block
78f try?
79 print 123
80 func!
81catch e
82 print e
83 e
84```
85<YueDisplay>
86
87```yue
88a, b, c = try? func!
89
90-- with nil coalescing operator
91a = (try? func!) ?? "default"
92
93-- as function argument
94f try? func!
95
96-- with catch block
97f try?
98 print 123
99 func!
100catch e
101 print e
102 e
103```
104
105</YueDisplay>
diff --git a/doc/docs/doc/usage.md b/doc/docs/doc/usage.md
new file mode 100644
index 0000000..45161c6
--- /dev/null
+++ b/doc/docs/doc/usage.md
@@ -0,0 +1,111 @@
1# Usage
2
3## Lua Module
4
5Use YueScript module in Lua:
6
7* **Case 1**
8
9 Require "your_yuescript_entry.yue" in Lua.
10 ```Lua
11 require("yue")("your_yuescript_entry")
12 ```
13 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.
14
15* **Case 2**
16
17 Require YueScript module and rewite message by hand.
18
19 ```lua
20 local yue = require("yue")
21 yue.insert_loader()
22 local success, result = xpcall(function()
23 return require("yuescript_module_name")
24 end, function(err)
25 return yue.traceback(err)
26 end)
27 ```
28
29* **Case 3**
30
31 Use the YueScript compiler function in Lua.
32
33 ```lua
34 local yue = require("yue")
35 local codes, err, globals = yue.to_lua([[
36 f = ->
37 print "hello world"
38 f!
39 ]],{
40 implicit_return_root = true,
41 reserve_line_number = true,
42 lint_global = true,
43 space_over_tab = false,
44 options = {
45 target = "5.4",
46 path = "/script"
47 }
48 })
49 ```
50
51## YueScript Tool
52
53Use YueScript tool with:
54
55```shell
56> yue -h
57Usage: yue
58 [options] [<file/directory>] ...
59 yue -e <code_or_file> [args...]
60 yue -w [<directory>] [options]
61 yue -
62
63Notes:
64 - '-' / '--' must be the first and only argument.
65 - '-o/--output' can not be used with multiple input files.
66 - '-w/--watch' can not be used with file input (directory only).
67 - with '-e/--execute', remaining tokens are treated as script args.
68
69Options:
70 -h, --help Show this help message and exit.
71 -e <str>, --execute <str> Execute a file or raw codes
72 -m, --minify Generate minified codes
73 -r, --rewrite Rewrite output to match original line numbers
74 -t <output_to>, --output-to <output_to>
75 Specify where to place compiled files
76 -o <file>, --output <file> Write output to file
77 -p, --print Write output to standard out
78 -b, --benchmark Dump compile time (doesn't write output)
79 -g, --globals Dump global variables used in NAME LINE COLUMN
80 -s, --spaces Use spaces in generated codes instead of tabs
81 -l, --line-numbers Write line numbers from source codes
82 -j, --no-implicit-return Disable implicit return at end of file
83 -c, --reserve-comments Reserve comments before statement from source codes
84 -w [<dir>], --watch [<dir>]
85 Watch changes and compile every file under directory
86 -v, --version Print version
87 - Read from standard in, print to standard out
88 (Must be first and only argument)
89 -- Same as '-' (kept for backward compatibility)
90
91 --target <version> Specify the Lua version that codes will be generated to
92 (version can only be 5.1 to 5.5)
93 --path <path_str> Append an extra Lua search path string to package.path
94 --<key>=<value> Pass compiler option in key=value form (existing behavior)
95
96 Execute without options to enter REPL, type symbol '$'
97 in a single line to start/stop multi-line mode
98```
99Use cases:
100
101Recursively compile every YueScript file with extension **.yue** under current path: **yue .**
102
103Compile and save results to a target path: **yue -t /target/path/ .**
104
105Compile and reserve debug info: **yue -l .**
106
107Compile and generate minified codes: **yue -m .**
108
109Execute raw codes: **yue -e 'print 123'**
110
111Execute a YueScript file: **yue -e main.yue**
diff --git a/doc/docs/doc/varargs-assignment.md b/doc/docs/doc/varargs-assignment.md
new file mode 100644
index 0000000..1d66680
--- /dev/null
+++ b/doc/docs/doc/varargs-assignment.md
@@ -0,0 +1,24 @@
1# Varargs Assignment
2
3You can assign the results returned from a function to a varargs symbol `...`. And then access its content using the Lua way.
4
5```yuescript
6list = [1, 2, 3, 4, 5]
7fn = (ok) -> ok, table.unpack list
8ok, ... = fn true
9count = select '#', ...
10first = select 1, ...
11print ok, count, first
12```
13<YueDisplay>
14
15```yue
16list = [1, 2, 3, 4, 5]
17fn = (ok) -> ok, table.unpack list
18ok, ... = fn true
19count = select '#', ...
20first = select 1, ...
21print ok, count, first
22```
23
24</YueDisplay>
diff --git a/doc/docs/doc/while-loop.md b/doc/docs/doc/while-loop.md
new file mode 100644
index 0000000..502935e
--- /dev/null
+++ b/doc/docs/doc/while-loop.md
@@ -0,0 +1,69 @@
1# While Loop
2
3The while loop also comes in four variations:
4
5```yuescript
6i = 10
7while i > 0
8 print i
9 i -= 1
10
11while running == true do my_function!
12```
13<YueDisplay>
14
15```yue
16i = 10
17while i > 0
18 print i
19 i -= 1
20
21while running == true do my_function!
22```
23
24</YueDisplay>
25
26```yuescript
27i = 10
28until i == 0
29 print i
30 i -= 1
31
32until running == false do my_function!
33```
34<YueDisplay>
35
36```yue
37i = 10
38until i == 0
39 print i
40 i -= 1
41until running == false do my_function!
42```
43
44</YueDisplay>
45
46Like for loops, the while loop can also be used an expression. Additionally, for a function to return the accumulated value of a while loop, the statement must be explicitly returned.
47
48## Repeat Loop
49
50The repeat loop comes from Lua:
51
52```yuescript
53i = 10
54repeat
55 print i
56 i -= 1
57until i == 0
58```
59<YueDisplay>
60
61```yue
62i = 10
63repeat
64 print i
65 i -= 1
66until i == 0
67```
68
69</YueDisplay>
diff --git a/doc/docs/doc/whitespace.md b/doc/docs/doc/whitespace.md
new file mode 100644
index 0000000..d742a2b
--- /dev/null
+++ b/doc/docs/doc/whitespace.md
@@ -0,0 +1,43 @@
1# Whitespace
2
3YueScript is a whitespace significant language. You have to write some code block in the same indent with space **' '** or tab **'\t'** like function body, value list and some control blocks. And expressions containing different whitespaces might mean different things. Tab is treated like 4 space, but it's better not mix the use of spaces and tabs.
4
5## Statement Separator
6
7A statement normally ends at a line break. You can also use a semicolon `;` to explicitly terminate a statement, which allows writing multiple statements on the same line:
8
9```yuescript
10a = 1; b = 2; print a + b
11```
12<YueDisplay>
13
14```yue
15a = 1; b = 2; print a + b
16```
17
18</YueDisplay>
19
20## Multiline Chaining
21
22You can write multi-line chaining function calls with a same indent.
23
24```yuescript
25Rx.Observable
26 .fromRange 1, 8
27 \filter (x) -> x % 2 == 0
28 \concat Rx.Observable.of 'who do we appreciate'
29 \map (value) -> value .. '!'
30 \subscribe print
31```
32<YueDisplay>
33
34```yue
35Rx.Observable
36 .fromRange 1, 8
37 \filter (x) -> x % 2 == 0
38 \concat Rx.Observable.of 'who do we appreciate'
39 \map (value) -> value .. '!'
40 \subscribe print
41```
42
43</YueDisplay>
diff --git a/doc/docs/doc/with-statement.md b/doc/docs/doc/with-statement.md
new file mode 100644
index 0000000..7786803
--- /dev/null
+++ b/doc/docs/doc/with-statement.md
@@ -0,0 +1,126 @@
1# With Statement
2
3
4A common pattern involving the creation of an object is calling a series of functions and setting a series of properties immediately after creating it.
5
6This results in repeating the name of the object multiple times in code, adding unnecessary noise. A common solution to this is to pass a table in as an argument which contains a collection of keys and values to overwrite. The downside to this is that the constructor of this object must support this form.
7
8The with block helps to alleviate this. Within a with block we can use a special statements that begin with either . or \ which represent those operations applied to the object we are using with on.
9
10For example, we work with a newly created object:
11
12```yuescript
13with Person!
14 .name = "Oswald"
15 \add_relative my_dad
16 \save!
17 print .name
18```
19<YueDisplay>
20
21```yue
22with Person!
23 .name = "Oswald"
24 \add_relative my_dad
25 \save!
26 print .name
27```
28
29</YueDisplay>
30
31The with statement can also be used as an expression which returns the value it has been giving access to.
32
33```yuescript
34file = with File "favorite_foods.txt"
35 \set_encoding "utf8"
36```
37<YueDisplay>
38
39```yue
40file = with File "favorite_foods.txt"
41 \set_encoding "utf8"
42```
43
44</YueDisplay>
45
46Or…
47
48```yuescript
49create_person = (name, relatives) ->
50 with Person!
51 .name = name
52 \add_relative relative for relative in *relatives
53
54me = create_person "Leaf", [dad, mother, sister]
55```
56<YueDisplay>
57
58```yue
59create_person = (name, relatives) ->
60 with Person!
61 .name = name
62 \add_relative relative for relative in *relatives
63
64me = create_person "Leaf", [dad, mother, sister]
65```
66
67</YueDisplay>
68
69In this usage, with can be seen as a special form of the K combinator.
70
71The expression in the with statement can also be an assignment, if you want to give a name to the expression.
72
73```yuescript
74with str := "Hello"
75 print "original:", str
76 print "upper:", \upper!
77```
78<YueDisplay>
79
80```yue
81with str := "Hello"
82 print "original:", str
83 print "upper:", \upper!
84```
85
86</YueDisplay>
87
88You can access special keys with `[]` in a `with` statement.
89
90```yuescript
91with tb
92 [1] = 1
93 print [2]
94 with [abc]
95 [3] = [2]\func!
96 ["key-name"] = value
97 [] = "abc" -- appending to "tb"
98```
99<YueDisplay>
100
101```yue
102with tb
103 [1] = 1
104 print [2]
105 with [abc]
106 [3] = [2]\func!
107 ["key-name"] = value
108 [] = "abc" -- appending to "tb"
109```
110
111</YueDisplay>
112
113`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.
114
115```yuescript
116with? obj
117 print obj.name
118```
119<YueDisplay>
120
121```yue
122with? obj
123 print obj.name
124```
125
126</YueDisplay>
diff --git a/doc/docs/index.md b/doc/docs/index.md
index 0ce1284..03a33dd 100644
--- a/doc/docs/index.md
+++ b/doc/docs/index.md
@@ -17,9 +17,8 @@ features:
17 details: Pipe, pattern matching, slicing, and destructuring without giving up Lua interop. 17 details: Pipe, pattern matching, slicing, and destructuring without giving up Lua interop.
18 - title: Rapid Iteration 18 - title: Rapid Iteration
19 details: Any feedback is welcome to help accelerate the language development and evolution! 19 details: Any feedback is welcome to help accelerate the language development and evolution!
20footer: MIT Licensed | Copyright © 2017-2026 Li Jin
21--- 20---
22 21
23## License & Copyright 22### License & Copyright
24 23
25MIT License. Copyright © 2017-2026 Li Jin. All rights reserved. 24MIT License. Copyright © 2017-2026 Li Jin. All rights reserved.
diff --git a/doc/docs/zh/doc/assignment.md b/doc/docs/zh/doc/assignment.md
new file mode 100644
index 0000000..49561fb
--- /dev/null
+++ b/doc/docs/zh/doc/assignment.md
@@ -0,0 +1,142 @@
1# 赋值
2
3&emsp;&emsp;月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过 **local** 和 **global** 声明来改变声明变量的作用范围。
4
5```yuescript
6hello = "world"
7a, b, c = 1, 2, 3
8hello = 123 -- 访问现有的变量
9```
10<YueDisplay>
11
12```yue
13hello = "world"
14a, b, c = 1, 2, 3
15hello = 123 -- 访问现有的变量
16```
17
18</YueDisplay>
19
20## 执行更新
21
22&emsp;&emsp;你可以使用各式二进制运算符执行更新赋值。
23
24```yuescript
25x = 1
26x += 1
27x -= 1
28x *= 10
29x /= 10
30x %= 10
31s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量
32arg or= "默认值"
33```
34<YueDisplay>
35
36```yue
37x = 1
38x += 1
39x -= 1
40x *= 10
41x /= 10
42x %= 10
43s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量
44arg or= "默认值"
45```
46
47</YueDisplay>
48
49## 链式赋值
50
51&emsp;&emsp;你可以进行链式赋值,将多个项目赋予相同的值。
52
53```yuescript
54a = b = c = d = e = 0
55x = y = z = f!
56```
57<YueDisplay>
58
59```yue
60a = b = c = d = e = 0
61x = y = z = f!
62```
63
64</YueDisplay>
65
66## 显式声明局部变量
67
68```yuescript
69do
70 local a = 1
71 local *
72 print "预先声明后续所有变量为局部变量"
73 x = -> 1 + y + z
74 y, z = 2, 3
75 global instance = Item\new!
76
77do
78 local X = 1
79 local ^
80 print "只预先声明后续大写的变量为局部变量"
81 a = 1
82 B = 2
83```
84<YueDisplay>
85
86```yue
87do
88 local a = 1
89 local *
90 print "预先声明后续所有变量为局部变量"
91 x = -> 1 + y + z
92 y, z = 2, 3
93 global instance = Item\new!
94
95do
96 local X = 1
97 local ^
98 print "只预先声明后续大写的变量为局部变量"
99 a = 1
100 B = 2
101```
102
103</YueDisplay>
104
105## 显式声明全局变量
106
107```yuescript
108do
109 global a = 1
110 global *
111 print "预先声明所有变量为全局变量"
112 x = -> 1 + y + z
113 y, z = 2, 3
114
115do
116 global x = 1
117 global ^
118 print "只预先声明大写的变量为全局变量"
119 a = 1
120 B = 2
121 local Temp = "一个局部值"
122```
123<YueDisplay>
124
125```yue
126do
127 global a = 1
128 global *
129 print "预先声明所有变量为全局变量"
130 x = -> 1 + y + z
131 y, z = 2, 3
132
133do
134 global x = 1
135 global ^
136 print "只预先声明大写的变量为全局变量"
137 a = 1
138 B = 2
139 local Temp = "一个局部值"
140```
141
142</YueDisplay>
diff --git a/doc/docs/zh/doc/attributes.md b/doc/docs/zh/doc/attributes.md
new file mode 100644
index 0000000..3dc3b0b
--- /dev/null
+++ b/doc/docs/zh/doc/attributes.md
@@ -0,0 +1,46 @@
1# 属性
2
3&emsp;&emsp;月之脚本现在提供了 Lua 5.4 新增的叫做属性的语法支持。在月之脚本编译到的 Lua 目标版本低于 5.4 时,你仍然可以同时使用`const` 和 `close` 的属性声明语法,并获得常量检查和作用域回调的功能。
4
5```yuescript
6const a = 123
7close _ = <close>: -> print "超出范围。"
8```
9<YueDisplay>
10
11```yue
12const a = 123
13close _ = <close>: -> print "超出范围。"
14```
15
16</YueDisplay>
17
18&emsp;&emsp;你可以对进行解构得到的变量标记为常量。
19
20```yuescript
21const {:a, :b, c, d} = tb
22-- a = 1
23```
24<YueDisplay>
25
26```yue
27const {:a, :b, c, d} = tb
28-- a = 1
29```
30
31</YueDisplay>
32
33&emsp;&emsp;你也可以声明全局变量为常量。
34
35```yuescript
36global const Constant = 123
37-- Constant = 1
38```
39<YueDisplay>
40
41```yue
42global const Constant = 123
43-- Constant = 1
44```
45
46</YueDisplay>
diff --git a/doc/docs/zh/doc/backcalls.md b/doc/docs/zh/doc/backcalls.md
new file mode 100644
index 0000000..4c32fac
--- /dev/null
+++ b/doc/docs/zh/doc/backcalls.md
@@ -0,0 +1,69 @@
1# 反向回调
2
3&emsp;&emsp;反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。
4
5```yuescript
6x <- f
7print "hello" .. x
8```
9<YueDisplay>
10
11```yue
12x <- f
13print "hello" .. x
14```
15
16</YueDisplay>
17
18&emsp;&emsp;月之脚本也提供了粗箭头反向回调函数。
19
20```yuescript
21<= f
22print @value
23```
24<YueDisplay>
25
26```yue
27<= f
28print @value
29```
30
31</YueDisplay>
32
33&emsp;&emsp;你可以通过一个占位符指定回调函数的传参位置。
34
35```yuescript
36(x) <- map _, [1, 2, 3]
37x * 2
38```
39<YueDisplay>
40
41```yue
42(x) <- map _, [1, 2, 3]
43x * 2
44```
45
46</YueDisplay>
47
48&emsp;&emsp;如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。
49
50```yuescript
51result, msg = do
52 data <- readAsync "文件名.txt"
53 print data
54 info <- processAsync data
55 check info
56print result, msg
57```
58<YueDisplay>
59
60```yue
61result, msg = do
62 data <- readAsync "文件名.txt"
63 print data
64 info <- processAsync data
65 check info
66print result, msg
67```
68
69</YueDisplay>
diff --git a/doc/docs/zh/doc/comment.md b/doc/docs/zh/doc/comment.md
new file mode 100644
index 0000000..f6a7b4e
--- /dev/null
+++ b/doc/docs/zh/doc/comment.md
@@ -0,0 +1,30 @@
1# 注释
2
3```yuescript
4-- 我是一个注释
5
6str = --[[
7这是一个多行注释。
8没问题。
9]] strA \ -- 注释 1
10 .. strB \ -- 注释 2
11 .. strC
12
13func --[[端口]] 3000, --[[ip]] "192.168.1.1"
14```
15<YueDisplay>
16
17```yue
18-- 我是一个注释
19
20str = --[[
21这是一个多行注释。
22没问题。
23]] strA \ -- 注释 1
24 .. strB \ -- 注释 2
25 .. strC
26
27func --[[端口]] 3000, --[[ip]] "192.168.1.1"
28```
29
30</YueDisplay>
diff --git a/doc/docs/zh/doc/comprehensions.md b/doc/docs/zh/doc/comprehensions.md
new file mode 100644
index 0000000..fd25b22
--- /dev/null
+++ b/doc/docs/zh/doc/comprehensions.md
@@ -0,0 +1,272 @@
1# 推导式
2
3&emsp;&emsp;推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生 Lua 表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许你在每次遍历时设置新表格的键和值。
4
5## 列表推导式
6
7&emsp;&emsp;以下操作创建了一个 items 表的副本,但所有包含的值都翻倍了。
8
9```yuescript
10items = [1, 2, 3, 4]
11doubled = [item * 2 for i, item in ipairs items]
12```
13<YueDisplay>
14
15```yue
16items = [1, 2, 3, 4]
17doubled = [item * 2 for i, item in ipairs items]
18```
19
20</YueDisplay>
21
22&emsp;&emsp;可以使用 `when` 子句筛选新表中包含的项目:
23
24```yuescript
25slice = [item for i, item in ipairs items when i > 1 and i < 3]
26```
27<YueDisplay>
28
29```yue
30slice = [item for i, item in ipairs items when i > 1 and i < 3]
31```
32
33</YueDisplay>
34
35&emsp;&emsp;因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled 示例可以重写为:
36
37```yuescript
38doubled = [item * 2 for item in *items]
39```
40<YueDisplay>
41
42```yue
43doubled = [item * 2 for item in *items]
44```
45
46</YueDisplay>
47
48&emsp;&emsp;在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理:
49
50```yuescript
51data =
52 a: [1, 2, 3]
53 b: [4, 5, 6]
54
55flat = [...v for k,v in pairs data]
56-- flat 现在为 [1, 2, 3, 4, 5, 6]
57```
58<YueDisplay>
59
60```yue
61data =
62 a: [1, 2, 3]
63 b: [4, 5, 6]
64
65flat = [...v for k,v in pairs data]
66-- flat 现在为 [1, 2, 3, 4, 5, 6]
67```
68
69</YueDisplay>
70
71&emsp;&emsp;for 和 when 子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个 for 子句。
72
73&emsp;&emsp;使用多个 for 子句与使用多重循环的效果相同:
74
75```yuescript
76x_coords = [4, 5, 6, 7]
77y_coords = [9, 2, 3]
78
79points = [ [x, y] for x in *x_coords \
80for y in *y_coords]
81```
82<YueDisplay>
83
84```yue
85x_coords = [4, 5, 6, 7]
86y_coords = [9, 2, 3]
87
88points = [ [x, y] for x in *x_coords \
89for y in *y_coords]
90```
91
92</YueDisplay>
93
94&emsp;&emsp;在推导式中也可以使用简单的数值 for 循环:
95
96```yuescript
97evens = [i for i = 1, 100 when i % 2 == 0]
98```
99<YueDisplay>
100
101```yue
102evens = [i for i = 1, 100 when i % 2 == 0]
103```
104
105</YueDisplay>
106
107## 表格推导式
108
109&emsp;&emsp;表格推导式和列表推导式的语法非常相似,只是要使用 **{** 和 **}** 并从每次迭代中取两个值。
110
111&emsp;&emsp;以下示例生成了表格 thing 的副本:
112
113```yuescript
114thing = {
115 color: "red"
116 name: "fast"
117 width: 123
118}
119
120thing_copy = {k, v for k, v in pairs thing}
121```
122<YueDisplay>
123
124```yue
125thing = {
126 color: "red"
127 name: "fast"
128 width: 123
129}
130
131thing_copy = {k, v for k, v in pairs thing}
132```
133
134</YueDisplay>
135
136```yuescript
137no_color = {k, v for k, v in pairs thing when k != "color"}
138```
139<YueDisplay>
140
141```yue
142no_color = {k, v for k, v in pairs thing when k != "color"}
143```
144
145</YueDisplay>
146
147&emsp;&emsp;**\*** 操作符在表格推导式中能使用。在下面的例子里,我们为几个数字创建了一个平方根查找表。
148
149```yuescript
150numbers = [1, 2, 3, 4]
151sqrts = {i, math.sqrt i for i in *numbers}
152```
153<YueDisplay>
154
155```yue
156numbers = [1, 2, 3, 4]
157sqrts = {i, math.sqrt i for i in *numbers}
158```
159
160</YueDisplay>
161
162&emsp;&emsp;表格推导式中的键值元组也可以来自单个表达式,在这种情况下,表达式在计算后应返回两个值。第一个用作键,第二个用作值:
163
164&emsp;&emsp;在下面的示例中,我们将一些数组转换为一个表,其中每个数组里的第一项是键,第二项是值。
165
166```yuescript
167tuples = [ ["hello", "world"], ["foo", "bar"]]
168tbl = {unpack tuple for tuple in *tuples}
169```
170<YueDisplay>
171
172```yue
173tuples = [ ["hello", "world"], ["foo", "bar"]]
174tbl = {unpack tuple for tuple in *tuples}
175```
176
177</YueDisplay>
178
179## 切片
180
181&emsp;&emsp;当使用 **\*** 操作符时,月之脚本还提供了一种特殊的语法来限制要遍历的列表范围。这个语法也相当于在 for 循环中设置迭代边界和步长。
182
183&emsp;&emsp;下面的案例中,我们在切片中设置最小和最大边界,取索引在 1 到 5 之间(包括 1 和 5)的所有项目:
184
185```yuescript
186slice = [item for item in *items[1, 5]]
187```
188<YueDisplay>
189
190```yue
191slice = [item for item in *items[1, 5]]
192```
193
194</YueDisplay>
195
196&emsp;&emsp;切片的任意参数都可以省略,并会使用默认值。在如下示例中,如果省略了最大索引边界,它默认为表的长度。使下面的代码取除第一个元素之外的所有元素:
197
198```yuescript
199slice = [item for item in *items[2,]]
200```
201<YueDisplay>
202
203```yue
204slice = [item for item in *items[2,]]
205```
206
207</YueDisplay>
208
209&emsp;&emsp;如果省略了最小边界,便默认会设置为 1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …)
210
211```yuescript
212slice = [item for item in *items[,,2]]
213```
214<YueDisplay>
215
216
217```yue
218slice = [item for item in *items[,,2]]
219```
220
221</YueDisplay>
222
223&emsp;&emsp;最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。
224
225```yuescript
226-- 取最后4个元素
227slice = [item for item in *items[-4,-1]]
228```
229<YueDisplay>
230
231```yue
232-- 取最后4个元素
233slice = [item for item in *items[-4,-1]]
234```
235
236</YueDisplay>
237
238&emsp;&emsp;切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。
239
240```yuescript
241reverse_slice = [item for item in *items[-1,1,-1]]
242```
243<YueDisplay>
244
245```yue
246reverse_slice = [item for item in *items[-1,1,-1]]
247```
248
249</YueDisplay>
250
251### 切片表达式
252
253&emsp;&emsp;切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。
254
255```yuescript
256-- 取第2和第4个元素作为新的列表
257sub_list = items[2, 4]
258
259-- 取最后4个元素作为新的列表
260last_four_items = items[-4, -1]
261```
262<YueDisplay>
263
264```yue
265-- 取第2和第4个元素作为新的列表
266sub_list = items[2, 4]
267
268-- 取最后4个元素作为新的列表
269last_four_items = items[-4, -1]
270```
271
272</YueDisplay>
diff --git a/doc/docs/zh/doc/conditionals.md b/doc/docs/zh/doc/conditionals.md
new file mode 100644
index 0000000..e4b217a
--- /dev/null
+++ b/doc/docs/zh/doc/conditionals.md
@@ -0,0 +1,150 @@
1# 条件语句
2
3```yuescript
4have_coins = false
5if have_coins
6 print "有硬币"
7else
8 print "没有硬币"
9```
10<YueDisplay>
11
12```yue
13have_coins = false
14if have_coins
15 print "有硬币"
16else
17 print "没有硬币"
18```
19
20</YueDisplay>
21
22&emsp;&emsp;对于简单的语句,也可以使用简短的语法:
23
24```yuescript
25have_coins = false
26if have_coins then print "有硬币" else print "没有硬币"
27```
28<YueDisplay>
29
30```yue
31have_coins = false
32if have_coins then print "有硬币" else print "没有硬币"
33```
34
35</YueDisplay>
36
37&emsp;&emsp;因为 if 语句可以用作表达式,所以也可以这样写:
38
39```yuescript
40have_coins = false
41print if have_coins then "有硬币" else "没有硬币"
42```
43<YueDisplay>
44
45```yue
46have_coins = false
47print if have_coins then "有硬币" else "没有硬币"
48```
49
50</YueDisplay>
51
52&emsp;&emsp;条件语句也可以作为表达式用在返回语句和赋值语句中:
53
54```yuescript
55is_tall = (name) ->
56 if name == "Rob"
57 true
58 else
59 false
60
61message = if is_tall "Rob"
62 "我很高"
63else
64 "我不是很高"
65
66print message -- 打印: 我很高
67```
68<YueDisplay>
69
70```yue
71is_tall = (name) ->
72 if name == "Rob"
73 true
74 else
75 false
76
77message = if is_tall "Rob"
78 "我很高"
79else
80 "我不是很高"
81
82print message -- 打印: 我很高
83```
84
85</YueDisplay>
86
87&emsp;&emsp;if 的反义词是 unless(相当于 if not,正如“如果”对应“除非”):
88
89```yuescript
90unless os.date("%A") == "Monday"
91 print "今天不是星期一!"
92```
93<YueDisplay>
94
95
96```yue
97unless os.date("%A") == "Monday"
98 print "今天不是星期一!"
99```
100
101</YueDisplay>
102
103```yuescript
104print "你真幸运!" unless math.random! > 0.1
105```
106<YueDisplay>
107
108```yue
109print "你真幸运!" unless math.random! > 0.1
110```
111
112</YueDisplay>
113
114## 范围表达式
115
116&emsp;&emsp;你可以使用范围表达式来编写进行范围检查的代码。
117
118```yuescript
119a = 5
120
121if a in [1, 3, 5, 7]
122 print "检查离散值的相等性"
123
124if a in list
125 print "检查`a`是否在列表中"
126```
127<YueDisplay>
128
129```yue
130a = 5
131
132if a in [1, 3, 5, 7]
133 print "检查离散值的相等性"
134
135if a in list
136 print "检查`a`是否在列表中"
137```
138
139</YueDisplay>
140
141```yuescript
142print "你很幸运!" unless math.random! > 0.1
143```
144<YueDisplay>
145
146```yue
147print "你很幸运!" unless math.random! > 0.1
148```
149
150</YueDisplay>
diff --git a/doc/docs/zh/doc/continue.md b/doc/docs/zh/doc/continue.md
new file mode 100644
index 0000000..9fab8a3
--- /dev/null
+++ b/doc/docs/zh/doc/continue.md
@@ -0,0 +1,41 @@
1# continue 语句
2
3&emsp;&emsp;继续语句可以用来跳出当前的循环迭代。
4
5```yuescript
6i = 0
7while i < 10
8 i += 1
9 continue if i % 2 == 0
10 print i
11```
12<YueDisplay>
13
14```yue
15i = 0
16while i < 10
17 i += 1
18 continue if i % 2 == 0
19 print i
20```
21
22</YueDisplay>
23
24&emsp;&emsp;继续语句也可以与各种循环表达式一起使用,以防止当前的循环迭代结果累积到结果列表中。以下示例将数组表过滤为仅包含偶数的数组:
25
26```yuescript
27my_numbers = [1, 2, 3, 4, 5, 6]
28odds = for x in *my_numbers
29 continue if x % 2 == 1
30 x
31```
32<YueDisplay>
33
34```yue
35my_numbers = [1, 2, 3, 4, 5, 6]
36odds = for x in *my_numbers
37 continue if x % 2 == 1
38 x
39```
40
41</YueDisplay>
diff --git a/doc/docs/zh/doc/destructuring-assignment.md b/doc/docs/zh/doc/destructuring-assignment.md
new file mode 100644
index 0000000..205a1ff
--- /dev/null
+++ b/doc/docs/zh/doc/destructuring-assignment.md
@@ -0,0 +1,241 @@
1# 解构赋值
2
3&emsp;&emsp;解构赋值是一种快速从 Lua 表中按名称或基于数组中的位置提取值的方法。
4
5&emsp;&emsp;通常当你看到一个字面量的 Lua 表,比如 `{1,2,3}`,它位于赋值的右侧,因为它是一个值。解构赋值语句的写法就是交换了字面量 Lua 表的角色,并将其放在赋值语句的左侧。
6
7&emsp;&emsp;最好是通过示例来解释。以下是如何从表格中解包前两个值的方法:
8
9```yuescript
10thing = [1, 2]
11
12[a, b] = thing
13print a, b
14```
15<YueDisplay>
16
17
18```yue
19thing = [1, 2]
20
21[a, b] = thing
22print a, b
23```
24
25</YueDisplay>
26
27&emsp;&emsp;在解构表格字面量中,键代表从右侧读取的键,值代表读取的值将被赋予的名称。
28
29```yuescript
30obj = {
31 hello: "world"
32 day: "tuesday"
33 length: 20
34}
35
36{hello: hello, day: the_day} = obj
37print hello, the_day
38
39:day = obj -- 可以不带大括号进行简单的解构
40```
41<YueDisplay>
42
43```yue
44obj = {
45 hello: "world"
46 day: "tuesday"
47 length: 20
48}
49
50{hello: hello, day: the_day} = obj
51print hello, the_day
52
53:day = obj -- 可以不带大括号进行简单的解构
54```
55
56</YueDisplay>
57
58&emsp;&emsp;这也适用于嵌套的数据结构:
59
60```yuescript
61obj2 = {
62 numbers: [1,2,3,4]
63 properties: {
64 color: "green"
65 height: 13.5
66 }
67}
68
69{numbers: [first, second], properties: {color: color}} = obj2
70print first, second, color
71```
72<YueDisplay>
73
74```yue
75obj2 = {
76 numbers: [1,2,3,4]
77 properties: {
78 color: "green"
79 height: 13.5
80 }
81}
82
83{numbers: [first, second]} = obj2
84print first, second, color
85```
86
87</YueDisplay>
88
89&emsp;&emsp;如果解构语句很复杂,也可以任意将其分散在几行中。稍微复杂一些的示例:
90
91```yuescript
92{
93 numbers: [first, second]
94 properties: {
95 color: color
96 }
97} = obj2
98```
99<YueDisplay>
100
101```yue
102{
103 numbers: [first, second]
104 properties: {
105 color: color
106 }
107} = obj2
108```
109
110</YueDisplay>
111
112&emsp;&emsp;有时候我们会需要从 Lua 表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符:
113
114```yuescript
115{:concat, :insert} = table
116```
117<YueDisplay>
118
119```yue
120{:concat, :insert} = table
121```
122
123</YueDisplay>
124
125&emsp;&emsp;这样的用法与导入语法有些相似。但我们可以通过混合语法重命名我们想要提取的字段:
126
127```yuescript
128{:mix, :max, random: rand} = math
129```
130<YueDisplay>
131
132```yue
133{:mix, :max, random: rand} = math
134```
135
136</YueDisplay>
137
138&emsp;&emsp;在进行解构时,你可以指定默认值,如:
139
140```yuescript
141{:name = "nameless", :job = "jobless"} = person
142```
143<YueDisplay>
144
145```yue
146{:name = "nameless", :job = "jobless"} = person
147```
148
149</YueDisplay>
150
151&emsp;&emsp;在进行列表解构时,你可以使用`_`作为占位符:
152
153```yuescript
154[_, two, _, four] = items
155```
156<YueDisplay>
157
158```yue
159[_, two, _, four] = items
160```
161
162</YueDisplay>
163
164## 范围解构
165
166&emsp;&emsp;你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。
167
168```yuescript
169orders = ["first", "second", "third", "fourth", "last"]
170[first, ...bulk, last] = orders
171print first -- 打印: first
172print bulk -- 打印: {"second", "third", "fourth"}
173print last -- 打印: last
174```
175<YueDisplay>
176
177```yue
178orders = ["first", "second", "third", "fourth", "last"]
179[first, ...bulk, last] = orders
180print first -- 打印: first
181print bulk -- 打印: {"second", "third", "fourth"}
182print last -- 打印: last
183```
184
185</YueDisplay>
186
187&emsp;&emsp;展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获:
188
189```yuescript
190-- 捕获第一个元素之后的所有元素
191[first, ...rest] = orders
192
193-- 捕获最后一个元素之前的所有元素
194[...start, last] = orders
195
196-- 跳过中间的元素,只捕获第一个和最后一个元素
197[first, ..._, last] = orders
198```
199<YueDisplay>
200
201```yue
202-- 捕获第一个元素之后的所有元素
203[first, ...rest] = orders
204
205-- 捕获最后一个元素之前的所有元素
206[...start, last] = orders
207
208-- 跳过中间的元素,只捕获第一个和最后一个元素
209[first, ..._, last] = orders
210```
211
212</YueDisplay>
213
214## 在其它地方的解构赋值
215
216&emsp;&emsp;解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在 for 循环中:
217
218```yuescript
219tuples = [
220 ["hello", "world"]
221 ["egg", "head"]
222]
223
224for [left, right] in *tuples
225 print left, right
226```
227<YueDisplay>
228
229```yue
230tuples = [
231 ["hello", "world"]
232 ["egg", "head"]
233]
234
235for [left, right] in *tuples
236 print left, right
237```
238
239</YueDisplay>
240
241&emsp;&emsp;我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在 for 语句的名称子句中使用解构来解包它。
diff --git a/doc/docs/zh/doc/do.md b/doc/docs/zh/doc/do.md
new file mode 100644
index 0000000..52dca26
--- /dev/null
+++ b/doc/docs/zh/doc/do.md
@@ -0,0 +1,66 @@
1# do 语句
2
3&emsp;&emsp;当用作语句时,do 语句的作用就像在 Lua 中差不多。
4
5```yuescript
6do
7 var = "hello"
8 print var
9print var -- 这里是nil
10```
11<YueDisplay>
12
13```yue
14do
15 var = "hello"
16 print var
17print var -- 这里是nil
18```
19
20</YueDisplay>
21
22&emsp;&emsp;月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将 do 语句代码块的最后一个语句作为表达式返回的结果。
23
24```yuescript
25counter = do
26 i = 0
27 ->
28 i += 1
29 i
30
31print counter!
32print counter!
33```
34<YueDisplay>
35
36```yue
37counter = do
38 i = 0
39 ->
40 i += 1
41 i
42
43print counter!
44print counter!
45```
46
47</YueDisplay>
48
49```yuescript
50tbl = {
51 key: do
52 print "分配键值!"
53 1234
54}
55```
56<YueDisplay>
57
58```yue
59tbl = {
60 key: do
61 print "分配键值!"
62 1234
63}
64```
65
66</YueDisplay>
diff --git a/doc/docs/zh/doc/for-loop.md b/doc/docs/zh/doc/for-loop.md
new file mode 100644
index 0000000..212ff81
--- /dev/null
+++ b/doc/docs/zh/doc/for-loop.md
@@ -0,0 +1,125 @@
1# for 循环
2
3&emsp;&emsp;Lua 中有两种 for 循环形式,数字型和通用型:
4
5```yuescript
6for i = 10, 20
7 print i
8
9for k = 1, 15, 2 -- 提供了一个遍历的步长
10 print k
11
12for key, value in pairs object
13 print key, value
14```
15<YueDisplay>
16
17```yue
18for i = 10, 20
19 print i
20
21for k = 1, 15, 2 -- 提供了一个遍历的步长
22 print k
23
24for key, value in pairs object
25 print key, value
26```
27
28</YueDisplay>
29
30&emsp;&emsp;可以使用切片和 **\*** 操作符,就像在列表推导中一样:
31
32```yuescript
33for item in *items[2, 4]
34 print item
35```
36<YueDisplay>
37
38```yue
39for item in *items[2, 4]
40 print item
41```
42
43</YueDisplay>
44
45&emsp;&emsp;当代码语句只有一行时,循环语句也都可以写作更短的语法:
46
47```yuescript
48for item in *items do print item
49
50for j = 1, 10, 3 do print j
51```
52<YueDisplay>
53
54```yue
55for item in *items do print item
56
57for j = 1, 10, 3 do print j
58```
59
60</YueDisplay>
61
62&emsp;&emsp;for 循环也可以用作表达式。for 循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。
63
64&emsp;&emsp;将每个偶数加倍:
65
66```yuescript
67doubled_evens = for i = 1, 20
68 if i % 2 == 0
69 i * 2
70 else
71 i
72```
73<YueDisplay>
74
75```yue
76doubled_evens = for i = 1, 20
77 if i % 2 == 0
78 i * 2
79 else
80 i
81```
82
83</YueDisplay>
84
85&emsp;&emsp;此外,for 循环还支持带返回值的 break 语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。
86
87&emsp;&emsp;例如,查找第一个大于 10 的数字:
88
89```yuescript
90first_large = for n in *numbers
91 break n if n > 10
92```
93<YueDisplay>
94
95```yue
96first_large = for n in *numbers
97 break n if n > 10
98```
99
100</YueDisplay>
101
102&emsp;&emsp;你还可以结合 for 循环表达式与 continue 语句来过滤值。
103
104&emsp;&emsp;注意出现在函数体末尾的 for 循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回 nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加 for 循环表达式。
105
106```yuescript
107func_a = -> for i = 1, 10 do print i
108func_b = -> return for i = 1, 10 do i
109
110print func_a! -- 打印 nil
111print func_b! -- 打印 table 对象
112```
113<YueDisplay>
114
115```yue
116func_a = -> for i = 1, 10 do print i
117func_b = -> return for i = 1, 10 do i
118
119print func_a! -- 打印 nil
120print func_b! -- 打印 table 对象
121```
122
123</YueDisplay>
124
125&emsp;&emsp;这样做是为了避免在不需要返回循环结果的函数,创建无效的返回值表格。
diff --git a/doc/docs/zh/doc/function-literals.md b/doc/docs/zh/doc/function-literals.md
new file mode 100644
index 0000000..efe920b
--- /dev/null
+++ b/doc/docs/zh/doc/function-literals.md
@@ -0,0 +1,494 @@
1# 函数字面量
2
3&emsp;&emsp;所有函数都是使用月之脚本的函数表达式创建的。一个简单的函数可以用箭头表示为:**->**。
4
5```yuescript
6my_function = ->
7my_function() -- 调用空函数
8```
9<YueDisplay>
10
11```yue
12my_function = ->
13my_function() -- 调用空函数
14```
15
16</YueDisplay>
17
18&emsp;&emsp;函数体可以是紧跟在箭头后的一个语句,或者是在后面的行上使用同样缩进的一系列语句:
19
20```yuescript
21func_a = -> print "你好,世界"
22
23func_b = ->
24 value = 100
25 print "这个值是:", value
26```
27<YueDisplay>
28
29```yue
30func_a = -> print "你好,世界"
31
32func_b = ->
33 value = 100
34 print "这个值是:", value
35```
36
37</YueDisplay>
38
39&emsp;&emsp;如果一个函数没有参数,可以使用 **\!** 操作符调用它,而不是空括号。使用 **\!** 调用没有参数的函数是推荐的写法。
40
41```yuescript
42func_a!
43func_b()
44```
45<YueDisplay>
46
47```yue
48func_a!
49func_b()
50```
51
52</YueDisplay>
53
54&emsp;&emsp;带有参数的函数可以通过在箭头前加上括号中的参数名列表来进行创建:
55
56```yuescript
57sum = (x, y) -> print "数字的和", x + y
58```
59<YueDisplay>
60
61```yue
62sum = (x, y) -> print "数字的和", x + y
63```
64
65</YueDisplay>
66
67&emsp;&emsp;函数可以通过在函数名后列出参数来调用。当对函数做嵌套的调用时,后面列出的参数会应用于左侧最近的函数。
68
69```yuescript
70sum 10, 20
71print sum 10, 20
72
73a b c "a", "b", "c"
74```
75<YueDisplay>
76
77```yue
78sum 10, 20
79print sum 10, 20
80
81a b c "a", "b", "c"
82```
83
84</YueDisplay>
85
86&emsp;&emsp;为了避免在调用函数时产生歧义,也可以使用括号将参数括起来。比如在以下的例子中是必需的,这样才能确保参数被传入到正确的函数。
87
88```yuescript
89print "x:", sum(10, 20), "y:", sum(30, 40)
90```
91<YueDisplay>
92
93```yue
94print "x:", sum(10, 20), "y:", sum(30, 40)
95```
96
97</YueDisplay>
98
99&emsp;&emsp;注意:函数名与开始括号之间不能有任何空格。
100
101&emsp;&emsp;函数会将函数体中的最后一个语句强制转换为返回语句,这被称作隐式返回:
102
103```yuescript
104sum = (x, y) -> x + y
105print "数字的和是", sum 10, 20
106```
107<YueDisplay>
108
109```yue
110sum = (x, y) -> x + y
111print "数字的和是", sum 10, 20
112```
113
114</YueDisplay>
115
116&emsp;&emsp;如果你需要做显式返回,可以使用 return 关键字:
117
118```yuescript
119sum = (x, y) -> return x + y
120```
121<YueDisplay>
122
123```yue
124sum = (x, y) -> return x + y
125```
126
127</YueDisplay>
128
129&emsp;&emsp;就像在Lua中一样,函数可以返回多个值。最后一个语句必须是由逗号分隔的值列表:
130
131```yuescript
132mystery = (x, y) -> x + y, x - y
133a, b = mystery 10, 20
134```
135<YueDisplay>
136
137```yue
138mystery = (x, y) -> x + y, x - y
139a, b = mystery 10, 20
140```
141
142</YueDisplay>
143
144## 粗箭头
145
146&emsp;&emsp;因为在 Lua 中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含 self 参数的函数。
147
148```yuescript
149func = (num) => @value + num
150```
151<YueDisplay>
152
153```yue
154func = (num) => @value + num
155```
156
157</YueDisplay>
158
159## 参数默认值
160
161&emsp;&emsp;可以为函数的参数提供默认值。如果参数的值为 nil,则确定该参数为空。任何具有默认值的 nil 参数在函数体运行之前都会被替换。
162
163```yuescript
164my_function = (name = "某物", height = 100) ->
165 print "你好,我是", name
166 print "我的高度是", height
167```
168<YueDisplay>
169
170```yue
171my_function = (name = "某物", height = 100) ->
172 print "你好,我是", name
173 print "我的高度是", height
174```
175
176</YueDisplay>
177
178&emsp;&emsp;函数参数的默认值表达式在函数体中会按参数声明的顺序进行计算。因此,在默认值的表达式中可以访问先前声明的参数。
179
180```yuescript
181some_args = (x = 100, y = x + 1000) ->
182 print x + y
183```
184<YueDisplay>
185
186```yue
187some_args = (x = 100, y = x + 1000) ->
188 print x + y
189```
190
191</YueDisplay>
192
193## 注意事项
194
195&emsp;&emsp;由于月之脚本支持无需括号的表达式式函数调用,因此为了避免因空白字符造成的解析歧义,需要进行一些限制。
196
197&emsp;&emsp;减号(-)在表达式中既可以作为一元取反操作符,也可以作为二元减法操作符。请注意下面这些示例的编译方式:
198
199```yuescript
200a = x - 10
201b = x-10
202c = x -y
203d = x- z
204```
205<YueDisplay>
206
207```yue
208a = x - 10
209b = x-10
210c = x -y
211d = x- z
212```
213
214</YueDisplay>
215
216&emsp;&emsp;当函数调用的第一个参数是字符串字面量时,可以通过空白控制其优先级。在 Lua 中,常见的写法是调用仅有一个字符串或表字面量参数的函数时省略括号。
217
218&emsp;&emsp;当变量名和字符串字面量之间没有空格时,函数的调用优先级高于后续表达式,因此此时无法再传入其他参数。
219
220&emsp;&emsp;当变量名和字符串字面量之间有空格时,字符串字面量会作为后续表达式(如果存在)的参数,这样可以传递参数列表。
221
222```yuescript
223x = func"hello" + 100
224y = func "hello" + 100
225```
226<YueDisplay>
227
228```yue
229x = func"hello" + 100
230y = func "hello" + 100
231```
232
233</YueDisplay>
234
235## 多行参数
236
237&emsp;&emsp;当调用接收大量参数的函数时,将参数列表分成多行是很方便的。由于月之脚本语言对空白字符的敏感性,做参数列表的分割时务必要小心。
238
239&emsp;&emsp;如果要将参数列表写到下一行,那么当前行必须以逗号结束。并且下一行的缩进必须比当前的缩进多。一旦做了参数的缩进,所有其他参数列表的行必须保持相同的缩进级别,以成为参数列表的一部分。
240
241```yuescript
242my_func 5, 4, 3,
243 8, 9, 10
244
245cool_func 1, 2,
246 3, 4,
247 5, 6,
248 7, 8
249```
250<YueDisplay>
251
252```yue
253my_func 5, 4, 3,
254 8, 9, 10
255
256cool_func 1, 2,
257 3, 4,
258 5, 6,
259 7, 8
260```
261
262</YueDisplay>
263
264&emsp;&emsp;这种调用方式可以做嵌套。并通过缩进级别来确定参数属于哪一个函数。
265
266```yuescript
267my_func 5, 6, 7,
268 6, another_func 6, 7, 8,
269 9, 1, 2,
270 5, 4
271```
272<YueDisplay>
273
274```yue
275my_func 5, 6, 7,
276 6, another_func 6, 7, 8,
277 9, 1, 2,
278 5, 4
279```
280
281</YueDisplay>
282
283&emsp;&emsp;因为 Lua 表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是 Lua 表的一部分。
284
285```yuescript
286x = [
287 1, 2, 3, 4, a_func 4, 5,
288 5, 6,
289 8, 9, 10
290]
291```
292<YueDisplay>
293
294```yue
295x = [
296 1, 2, 3, 4, a_func 4, 5,
297 5, 6,
298 8, 9, 10
299]
300```
301
302</YueDisplay>
303
304&emsp;&emsp;有个不常见的写法可以注意一下,如果我们将在后面使用较低的缩进,我们可以为函数参数提供更深的缩进来区分列表的归属。
305
306```yuescript
307y = [ my_func 1, 2, 3,
308 4, 5,
309 5, 6, 7
310]
311```
312<YueDisplay>
313
314```yue
315y = [ my_func 1, 2, 3,
316 4, 5,
317 5, 6, 7
318]
319```
320
321</YueDisplay>
322
323&emsp;&emsp;对于其它有代码块跟随的语句,比如条件语句,也可以通过小心安排缩进来做类似的事。比如我们可以通过调整缩进级别来控制一些值归属于哪个语句:
324
325```yuescript
326if func 1, 2, 3,
327 "你好",
328 "世界"
329 print "你好"
330 print "我在if内部"
331
332if func 1, 2, 3,
333 "你好",
334 "世界"
335 print "hello"
336 print "我在if内部"
337```
338<YueDisplay>
339
340```yue
341if func 1, 2, 3,
342 "你好",
343 "世界"
344 print "你好"
345 print "我在if内部"
346
347if func 1, 2, 3,
348 "你好",
349 "世界"
350 print "你好"
351 print "我在if内部"
352```
353
354</YueDisplay>
355
356## 参数解构
357
358&emsp;&emsp;月之脚本支持在函数形参位置对传入对象进行解构。适用两类解构表子面量:
359
360- 使用 {} 包裹的字面量/对象形参,支持提供获得空字段时的默认值(例如 {:a, :b}、{a: a1 = 123})。
361
362- 无 {} 包裹、以键值/简写键序列开头,直至遇到其它表达式终止(例如 :a, b: b1, :c),表示从同一个对象中解构多个字段。
363
364```yuescript
365f1 = (:a, :b, :c) ->
366 print a, b, c
367
368f1 a: 1, b: "2", c: {}
369
370f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
371 print a1, b, c
372
373arg1 = {a: 0}
374f2 arg1, arg2
375```
376<YueDisplay>
377
378```yue
379f1 = (:a, :b, :c) ->
380 print a, b, c
381
382f1 a: 1, b: "2", c: {}
383
384f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
385 print a1, b, c
386
387arg1 = {a: 0}
388f2 arg1, arg2
389```
390
391</YueDisplay>
392
393## 前置返回表达式
394
395&emsp;&emsp;在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下:
396
397```yuescript
398findFirstEven = (list): nil ->
399 for item in *list
400 if type(item) == "table"
401 for sub in *item
402 if sub % 2 == 0
403 return sub
404```
405<YueDisplay>
406
407```yue
408findFirstEven = (list): nil ->
409 for item in *list
410 if type(item) == "table"
411 for sub in *item
412 if sub % 2 == 0
413 return sub
414```
415
416</YueDisplay>
417
418&emsp;&emsp;这个写法等价于:
419
420```yuescript
421findFirstEven = (list) ->
422 for item in *list
423 if type(item) == "table"
424 for sub in *item
425 if sub % 2 == 0
426 return sub
427 nil
428```
429<YueDisplay>
430
431```yue
432findFirstEven = (list) ->
433 for item in *list
434 if type(item) == "table"
435 for sub in *item
436 if sub % 2 == 0
437 return sub
438 nil
439```
440
441</YueDisplay>
442
443&emsp;&emsp;唯一的区别在于:你可以将函数的返回值表达式提前写在 `->` 或 `=>` 前,用以指示该函数应隐式返回该表达式的值。这样即使在多层循环或条件判断的场景下,也无需编写尾行悬挂的返回表达式,逻辑结构会更加直观清晰。
444
445## 命名变长参数
446
447&emsp;&emsp;你可以使用 `(...t) ->` 语法来将变长参数自动存储到一个命名表中。这个表会包含所有传入的参数(包括 `nil` 值),并且会在表的 `n` 字段中存储实际传入的参数个数(包括 `nil` 值在内的个数)。
448
449```yuescript
450f = (...t) ->
451 print "参数个数:", t.n
452 print "表长度:", #t
453 for i = 1, t.n
454 print t[i]
455
456f 1, 2, 3
457f "a", "b", "c", "d"
458f!
459
460-- 处理包含 nil 的情况
461process = (...args) ->
462 sum = 0
463 for i = 1, args.n
464 if args[i] != nil and type(args[i]) == "number"
465 sum += args[i]
466 sum
467
468process 1, nil, 3, nil, 5
469```
470<YueDisplay>
471
472```yue
473f = (...t) ->
474 print "参数个数:", t.n
475 print "表长度:", #t
476 for i = 1, t.n
477 print t[i]
478
479f 1, 2, 3
480f "a", "b", "c", "d"
481f!
482
483-- 处理包含 nil 的情况
484process = (...args) ->
485 sum = 0
486 for i = 1, args.n
487 if args[i] != nil and type(args[i]) == "number"
488 sum += args[i]
489 sum
490
491process 1, nil, 3, nil, 5
492```
493
494</YueDisplay>
diff --git a/doc/docs/zh/doc/function-stubs.md b/doc/docs/zh/doc/function-stubs.md
new file mode 100644
index 0000000..af08feb
--- /dev/null
+++ b/doc/docs/zh/doc/function-stubs.md
@@ -0,0 +1,48 @@
1# 函数存根
2
3&emsp;&emsp;在编程中,将对象的方法作为函数类型的值进行传递是一种常见做法,尤其是在将实例方法作为回调函数传递给其他函数的情形中。当目标函数需要将该对象作为其第一个参数时,我们需要找到一种方式将对象和函数绑定在一起,以便能够正确地调用该函数。
4
5&emsp;&emsp;函数存根(stub)语法提供了一种便捷的方法来创建一个新的闭包函数,这个函数将对象和原函数绑定在一起。这样,当调用这个新创建的函数时,它会在正确的对象上下文中执行原有的函数。
6
7&emsp;&emsp;这种语法类似于使用 \ 操作符调用实例方法的方式,区别在于,这里不需要在 \ 操作符后面附加参数列表。
8
9```yuescript
10my_object = {
11 value: 1000
12 write: => print "值为:", @value
13}
14
15run_callback = (func) ->
16 print "运行回调..."
17 func!
18
19-- 这样写不起作用:
20-- 函数没有引用my_object
21run_callback my_object.write
22
23-- 函数存根语法
24-- 让我们把对象捆绑到一个新函数中
25run_callback my_object\write
26```
27<YueDisplay>
28
29```yue
30my_object = {
31 value: 1000
32 write: => print "值为:", @value
33}
34
35run_callback = (func) ->
36 print "运行回调..."
37 func!
38
39-- 这样写不起作用:
40-- 函数没有引用my_object
41run_callback my_object.write
42
43-- 函数存根语法
44-- 让我们把对象捆绑到一个新函数中
45run_callback my_object\write
46```
47
48</YueDisplay>
diff --git a/doc/docs/zh/doc/if-assignment.md b/doc/docs/zh/doc/if-assignment.md
new file mode 100644
index 0000000..e4077e1
--- /dev/null
+++ b/doc/docs/zh/doc/if-assignment.md
@@ -0,0 +1,73 @@
1# If 赋值
2
3&emsp;&emsp;`if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。注意,你必须使用“海象运算符” `:=` 而不是 `=` 来做赋值。
4
5```yuescript
6if user := database.find_user "moon"
7 print user.name
8```
9<YueDisplay>
10
11```yue
12if user := database.find_user "moon"
13 print user.name
14```
15
16</YueDisplay>
17
18```yuescript
19if hello := os.getenv "hello"
20 print "你有 hello", hello
21elseif world := os.getenv "world"
22 print "你有 world", world
23else
24 print "什么都没有 :("
25```
26<YueDisplay>
27
28```yue
29if hello := os.getenv "hello"
30 print "你有 hello", hello
31elseif world := os.getenv "world"
32 print "你有 world", world
33else
34 print "什么都没有 :("
35```
36
37</YueDisplay>
38
39&emsp;&emsp;使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。
40
41```yuescript
42if success, result := pcall -> "无报错地获取结果"
43 print result -- 变量 result 是有作用域的
44print "好的"
45```
46<YueDisplay>
47
48```yue
49if success, result := pcall -> "无报错地获取结果"
50 print result -- 变量 result 是有作用域的
51print "好的"
52```
53
54</YueDisplay>
55
56## While 赋值
57
58&emsp;&emsp;你可以在 while 循环中同样使用赋值来获取循环条件的值。
59
60```yuescript
61while byte := stream\read_one!
62 -- 对 byte 做一些操作
63 print byte
64```
65<YueDisplay>
66
67```yue
68while byte := stream\read_one!
69 -- 对 byte 做一些操作
70 print byte
71```
72
73</YueDisplay>
diff --git a/doc/docs/zh/doc/index.md b/doc/docs/zh/doc/index.md
index 5250325..7611fc6 100755
--- a/doc/docs/zh/doc/index.md
+++ b/doc/docs/zh/doc/index.md
@@ -1,5453 +1,11 @@
1--- 1---
2sidebar: auto
3title: 参考手册 2title: 参考手册
4--- 3---
5 4
6# 月之脚本 5# 月之脚本文档
7 6
8<img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em;"/> 7<img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em;padding-bottom: 2em;"/>
9 8
10## 介绍 9欢迎来到 <b>月之脚本(YueScript)</b> 官方文档!<br/>
11 10这里收录了语言特性、用法、参考示例和资源。<br/>
12月之脚本(YueScript)是一种动态语言,可以编译为 Lua。它是 [MoonScript](https://github.com/leafo/moonscript) 的方言。用月之脚本编写的代码既有表现力又非常简洁。它适合编写一些更易于维护的代码,并在嵌入 Lua 的环境中运行,如游戏或网站服务器。 11请选择左侧的章节索引或目录,开启你的月之脚本之旅 ☽
13
14Yue(月)是中文中“月亮”的名称。
15
16### 月之脚本概览
17```yuescript
18-- 导入语法
19import p, to_lua from "yue"
20
21-- 隐式对象
22inventory =
23 equipment:
24 - "sword"
25 - "shield"
26 items:
27 - name: "potion"
28 count: 10
29 - name: "bread"
30 count: 3
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
42-- 管道操作符
43[1, 2, 3]
44 |> map (x) -> x * 2
45 |> filter (x) -> x > 4
46 |> reduce 0, (a, b) -> a + b
47 |> print
48
49-- 元表操作
50apple =
51 size: 15
52 <index>:
53 color: 0x00ffff
54
55with apple
56 p .size, .color, .<index> if .<>?
57
58-- 类似js的导出语法
59export 🌛 = "月之脚本"
60```
61<YueDisplay>
62
63```yue
64-- 导入语法
65import p, to_lua from "yue"
66
67-- 隐式对象
68inventory =
69 equipment:
70 - "sword"
71 - "shield"
72 items:
73 - name: "potion"
74 count: 10
75 - name: "bread"
76 count: 3
77
78-- 列表推导
79map = (arr, action) ->
80 [action item for item in *arr]
81
82filter = (arr, cond) ->
83 [item for item in *arr when cond item]
84
85reduce = (arr, init, action): init ->
86 init = action init, item for item in *arr
87
88-- 管道操作符
89[1, 2, 3]
90 |> map (x) -> x * 2
91 |> filter (x) -> x > 4
92 |> reduce 0, (a, b) -> a + b
93 |> print
94
95-- 元表操作
96apple =
97 size: 15
98 <index>:
99 color: 0x00ffff
100
101with apple
102 p .size, .color, .<index> if .<>?
103
104-- 类似js的导出语法
105export 🌛 = "月之脚本"
106```
107
108</YueDisplay>
109
110## 安装
111
112* **Lua 模块**
113
114&emsp;安装 [luarocks](https://luarocks.org),一个 Lua 模块的包管理器。然后作为 Lua 模块和可执行文件安装它:
115
116```
117> luarocks install yuescript
118```
119
120&emsp;或者你可以自己构建 `yue.so` 文件:
121
122```
123> make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua
124```
125
126&emsp;然后从路径 **bin/shared/yue.so** 获取二进制文件。
127
128* **构建二进制工具**
129
130&emsp;克隆项目仓库,然后构建并安装可执行文件:
131```
132> make install
133```
134
135&emsp;构建不带宏功能的月之脚本编译工具:
136```
137> make install NO_MACRO=true
138```
139
140&emsp;构建不带内置Lua二进制文件的月之脚本编译工具:
141```
142> make install NO_LUA=true
143```
144
145* **下载预编译的二进制程序**
146
147&emsp;你可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。
148
149&emsp;在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。
150
151## 使用方法
152
153### Lua 模块
154
155在 Lua 中使用月之脚本模块:
156
157* **用法 1**
158在 Lua 中引入 "你的脚本入口文件.yue"。
159```Lua
160require("yue")("你的脚本入口文件")
161```
162当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import** 进行脚本引用即可。错误消息中的代码行号也会被正确处理。
163
164* **用法 2**
165手动引入月之脚本模块并重写错误消息来帮助调试。
166```lua
167local yue = require("yue")
168yue.insert_loaders()
169local success, result = xpcall(function()
170 return require("yuescript_module_name")
171end, function(err)
172 return yue.traceback(err)
173end)
174```
175
176* **用法 3**
177在 Lua 中使用月之脚本编译器功能。
178```lua
179local yue = require("yue")
180local codes, err, globals = yue.to_lua([[
181f = ->
182 print "hello world"
183f!
184]],{
185 implicit_return_root = true,
186 reserve_line_number = true,
187 lint_global = true,
188 space_over_tab = false,
189 options = {
190 target = "5.4",
191 path = "/script"
192 }
193})
194```
195
196### 月之脚本编译工具
197
198使用月之脚本编译工具:
199```sh
200命令行用法: yue
201 [选项] [<文件/目录>] ...
202 yue -e <代码或文件> [参数...]
203 yue -w [<目录>] [选项]
204 yue -
205
206说明:
207 - '-' 或 '--' 必须作为唯一且第一个参数,用于读取标准输入。
208 - '-o/--output' 不能与多个输入文件一起使用。
209 - '-w/--watch' 仅能用于目录,不能用于单个文件。
210 - 使用 '-e/--execute' 时,后续的参数将作为脚本参数传递。
211
212选项:
213 -h, --help 显示帮助信息并退出
214 -e <字符串>, --execute <字符串> 执行文件或原始代码
215 -m, --minify 生成压缩(最小化)代码
216 -r, --rewrite 重写输出以匹配原始代码行号
217 -t <目标路径>, --output-to <目标路径>
218 指定编译后文件的输出路径
219 -o <文件>, --output <文件> 将输出写入文件
220 -p, --print 输出到标准输出
221 -b, --benchmark 输出编译耗时(不写入文件)
222 -g, --globals 显示用到的全局变量及其所在的名称、行号、列号
223 -s, --spaces 用空格代替制表符(tab)输出代码
224 -l, --line-numbers 输出源代码的行号
225 -j, --no-implicit-return 禁用文件末尾的隐式返回
226 -c, --reserve-comments 保留源代码中的注释
227 -w [<目录>], --watch [<目录>]
228 监视目录变化并自动编译
229 -v, --version 显示版本信息
230 - 从标准输入读取,输出到标准输出(仅能作为唯一参数)
231 -- 等同于 '-',为兼容旧版本保留
232
233 --target <版本> 指定生成代码的 Lua 版本 (只能为 5.1 ~ 5.5)
234 --path <路径字符串> 附加一个 Lua 搜索路径到 package.path
235 --<键>=<值> 以 key=value 形式传递编译器选项(保持已有用法)
236
237 不带选项直接运行可进入交互模式(REPL),在交互模式里输入单独的符号 '$'
238 可用于开始或结束多行模式。
239```
240&emsp;&emsp;使用案例:
241&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .**
242&emsp;&emsp;编译并将结果保存到目标路径: **yue -t /target/path/ .**
243&emsp;&emsp;编译并保留调试信息: **yue -l .**
244&emsp;&emsp;编译并生成压缩代码: **yue -m .**
245&emsp;&emsp;直接执行代码: **yue -e 'print 123'**
246&emsp;&emsp;执行一个月之脚本文件: **yue -e main.yue**
247
248## 宏
249
250### 常见用法
251
252宏函数用于在编译时执行一段代码来生成新的代码,并将生成的代码插入到最终编译结果中。
253
254```yuescript
255macro PI2 = -> math.pi * 2
256area = $PI2 * 5
257
258macro HELLO = -> "'你好 世界'"
259print $HELLO
260
261macro config = (debugging) ->
262 global debugMode = debugging == "true"
263 ""
264
265macro asserts = (cond) ->
266 debugMode and "assert #{cond}" or ""
267
268macro assert = (cond) ->
269 debugMode and "assert #{cond}" or "#{cond}"
270
271$config true
272$asserts item ~= nil
273
274$config false
275value = $assert item
276
277-- 宏函数参数传递的表达式会被转换为字符串
278macro and = (...) -> "#{ table.concat {...}, ' and ' }"
279if $and f1!, f2!, f3!
280 print "OK"
281```
282<YueDisplay>
283
284```yue
285macro PI2 = -> math.pi * 2
286area = $PI2 * 5
287
288macro HELLO = -> "'你好 世界'"
289print $HELLO
290
291macro config = (debugging) ->
292 global debugMode = debugging == "true"
293 ""
294
295macro asserts = (cond) ->
296 debugMode and "assert #{cond}" or ""
297
298macro assert = (cond) ->
299 debugMode and "assert #{cond}" or "#{cond}"
300
301$config true
302$asserts item ~= nil
303
304$config false
305value = $assert item
306
307-- 宏函数参数传递的表达式会被转换为字符串
308macro and = (...) -> "#{ table.concat {...}, ' and ' }"
309if $and f1!, f2!, f3!
310 print "OK"
311```
312
313</YueDisplay>
314
315### 直接插入代码
316
317宏函数可以返回一个包含月之脚本代码的字符串,或是一个包含 Lua 代码字符串的配置表。
318```yuescript
319macro yueFunc = (var) -> "local #{var} = ->"
320$yueFunc funcA
321funcA = -> "无法访问宏生成月之脚本里定义的变量"
322
323macro luaFunc = (var) -> {
324 code: "local function #{var}() end"
325 type: "lua"
326}
327$luaFunc funcB
328funcB = -> "无法访问宏生成 Lua 代码里定义的变量"
329
330macro lua = (code) -> {
331 :code
332 type: "lua"
333}
334
335-- raw字符串的开始和结束符号会自动被去除了再传入宏函数
336$lua[==[
337-- 插入原始Lua代码
338if cond then
339 print("输出")
340end
341]==]
342```
343<YueDisplay>
344
345```yue
346macro yueFunc = (var) -> "local #{var} = ->"
347$yueFunc funcA
348funcA = -> "无法访问宏生成月之脚本里定义的变量"
349
350macro luaFunc = (var) -> {
351 code: "local function #{var}() end"
352 type: "lua"
353}
354$luaFunc funcB
355funcB = -> "无法访问宏生成 Lua 代码里定义的变量"
356
357macro lua = (code) -> {
358 :code
359 type: "lua"
360}
361
362-- raw字符串的开始和结束符号会自动被去除了再传入宏函数
363$lua[==[
364-- 插入原始Lua代码
365if cond then
366 print("输出")
367end
368]==]
369```
370
371</YueDisplay>
372
373### 导出宏
374
375宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。
376```yuescript
377-- 文件: utils.yue
378export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
379export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
380export macro foreach = (items, action) -> "for _ in *#{items}
381 #{action}"
382
383-- 文件 main.yue
384import "utils" as {
385 $, -- 表示导入所有宏的符号
386 $foreach: $each -- 重命名宏 $foreach 为 $each
387}
388[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
389```
390<YueDisplay>
391
392```yue
393-- 文件: utils.yue
394export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
395export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
396export macro foreach = (items, action) -> "for _ in *#{items}
397 #{action}"
398-- 文件 main.yue
399-- 在浏览器中不支持import函数,请在真实环境中尝试
400--[[
401import "utils" as {
402 $, -- 表示导入所有宏的符号
403 $foreach: $each -- 重命名宏 $foreach 为 $each
404}
405[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
406]]
407```
408
409</YueDisplay>
410
411### 内置宏
412
413月之脚本中有一些内置可以直接使用的宏,但你可以通过声明相同名称的宏来覆盖它们。
414```yuescript
415print $FILE -- 获取当前模块名称的字符串
416print $LINE -- 获取当前代码行数:2
417```
418<YueDisplay>
419
420```yue
421print $FILE -- 获取当前模块名称的字符串
422print $LINE -- 获取当前代码行数:2
423```
424
425</YueDisplay>
426
427### 用宏生成宏
428
429在月之脚本中,宏函数允许你在编译时生成代码。通过嵌套的宏函数,你可以创建更复杂的生成模式。这个特性允许你定义一个宏函数,用它来生成另一个宏函数,从而实现更加动态的代码生成。
430
431```yuescript
432macro Enum = (...) ->
433 items = {...}
434 itemSet = {item, true for item in *items}
435 (item) ->
436 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
437 "\"#{item}\""
438
439macro BodyType = $Enum(
440 Static
441 Dynamic
442 Kinematic
443)
444
445print "有效的枚举类型:", $BodyType Static
446-- print "编译报错的枚举类型:", $BodyType Unknown
447```
448<YueDisplay>
449
450```yue
451macro Enum = (...) ->
452 items = {...}
453 itemSet = {item, true for item in *items}
454 (item) ->
455 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
456 "\"#{item}\""
457
458macro BodyType = $Enum(
459 Static
460 Dynamic
461 Kinematic
462)
463
464print "有效的枚举类型:", $BodyType Static
465-- print "编译报错的枚举类型:", $BodyType Unknown
466```
467
468</YueDisplay>
469
470### 宏参数检查
471
472可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。
473
474```yuescript
475macro printNumAndStr = (num `Num, str `String) -> |
476 print(
477 #{num}
478 #{str}
479 )
480
481$printNumAndStr 123, "hello"
482```
483<YueDisplay>
484
485```yue
486macro printNumAndStr = (num `Num, str `String) -> |
487 print(
488 #{num}
489 #{str}
490 )
491
492$printNumAndStr 123, "hello"
493```
494
495</YueDisplay>
496
497如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。
498
499```yuescript
500macro printNumAndStr = (num, str) ->
501 error "expected Num as first argument" unless $is_ast Num, num
502 error "expected String as second argument" unless $is_ast String, str
503 "print(#{num}, #{str})"
504
505$printNumAndStr 123, "hello"
506```
507<YueDisplay>
508
509```yue
510macro printNumAndStr = (num, str) ->
511 error "expected Num as first argument" unless $is_ast Num, num
512 error "expected String as second argument" unless $is_ast String, str
513 "print(#{num}, #{str})"
514
515$printNumAndStr 123, "hello"
516```
517
518</YueDisplay>
519
520更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。
521
522## 操作符
523
524Lua 的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。
525
526```yuescript
527tb\func! if tb ~= nil
528tb::func! if tb != nil
529```
530<YueDisplay>
531
532```yue
533tb\func! if tb ~= nil
534tb::func! if tb != nil
535```
536
537</YueDisplay>
538
539### 链式比较
540
541你可以在月之脚本中进行比较表达式的链式书写:
542
543```yuescript
544print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
545-- 输出:true
546
547a = 5
548print 1 <= a <= 10
549-- 输出:true
550```
551<YueDisplay>
552
553```yue
554print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
555-- 输出:true
556
557a = 5
558print 1 <= a <= 10
559-- 输出:true
560```
561
562</YueDisplay>
563
564可以注意一下链式比较表达式的求值行为:
565
566```yuescript
567v = (x) ->
568 print x
569 x
570
571print v(1) < v(2) <= v(3)
572--[[
573 输出:
574 2
575 1
576 3
577 true
578]]
579
580print v(1) > v(2) <= v(3)
581--[[
582 输出:
583 2
584 1
585 false
586]]
587```
588<YueDisplay>
589
590```yue
591v = (x) ->
592 print x
593 x
594
595print v(1) < v(2) <= v(3)
596--[[
597 输出:
598 2
599 1
600 3
601 true
602]]
603
604print v(1) > v(2) <= v(3)
605--[[
606 输出:
607 2
608 1
609 false
610]]
611```
612
613</YueDisplay>
614
615在上面的例子里,中间的表达式 `v(2)` 仅被计算一次,如果把表达式写成 `v(1) < v(2) and v(2) <= v(3)` 的方式,中间的 `v(2)` 才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。
616
617### 表追加
618
619**[] =** 操作符用于向 Lua 表的最后插入值。
620
621```yuescript
622tab = []
623tab[] = "Value"
624```
625<YueDisplay>
626
627```yue
628tab = []
629tab[] = "Value"
630```
631
632</YueDisplay>
633
634你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中:
635
636```yuescript
637tbA = [1, 2, 3]
638tbB = [4, 5, 6]
639tbA[] = ...tbB
640-- tbA 现在为 [1, 2, 3, 4, 5, 6]
641```
642<YueDisplay>
643
644```yue
645tbA = [1, 2, 3]
646tbB = [4, 5, 6]
647tbA[] = ...tbB
648-- tbA 现在为 [1, 2, 3, 4, 5, 6]
649```
650
651</YueDisplay>
652
653### 表扩展
654
655你可以使用前置 `...` 操作符在 Lua 表中插入数组表或哈希表。
656
657```yuescript
658parts =
659 * "shoulders"
660 * "knees"
661lyrics =
662 * "head"
663 * ...parts
664 * "and"
665 * "toes"
666
667copy = {...other}
668
669a = {1, 2, 3, x: 1}
670b = {4, 5, y: 1}
671merge = {...a, ...b}
672```
673<YueDisplay>
674
675```yue
676parts =
677 * "shoulders"
678 * "knees"
679lyrics =
680 * "head"
681 * ...parts
682 * "and"
683 * "toes"
684
685copy = {...other}
686
687a = {1, 2, 3, x: 1}
688b = {4, 5, y: 1}
689merge = {...a, ...b}
690```
691
692</YueDisplay>
693
694### 表反向索引
695
696你可以使用 **#** 操作符来反向索引表中的元素。
697
698```yuescript
699last = data.items[#]
700second_last = data.items[#-1]
701data.items[#] = 1
702```
703<YueDisplay>
704
705```yue
706last = data.items[#]
707second_last = data.items[#-1]
708data.items[#] = 1
709```
710
711</YueDisplay>
712
713### 元表
714
715**<>** 操作符可提供元表操作的快捷方式。
716
717* **元表创建**
718使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的 Lua 表。
719
720```yuescript
721mt = {}
722add = (right) => <>: mt, value: @value + right.value
723mt.__add = add
724
725a = <>: mt, value: 1
726-- 使用与临时变量名相同的字段名,将临时变量赋值给元表
727b = :<add>, value: 2
728c = <add>: mt.__add, value: 3
729
730d = a + b + c
731print d.value
732
733close _ = <close>: -> print "超出范围"
734```
735<YueDisplay>
736
737```yue
738mt = {}
739add = (right) => <>: mt, value: @value + right.value
740mt.__add = add
741
742a = <>: mt, value: 1
743-- 使用与临时变量名相同的字段名,将临时变量赋值给元表
744b = :<add>, value: 2
745c = <add>: mt.__add, value: 3
746
747d = a + b + c
748print d.value
749
750close _ = <close>: -> print "超出范围"
751```
752
753</YueDisplay>
754
755* **元表访问**
756使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。
757
758```yuescript
759-- 使用包含字段 "value" 的元表创建
760tb = <"value">: 123
761tb.<index> = tb.<>
762print tb.value
763
764tb.<> = __index: {item: "hello"}
765print tb.item
766```
767<YueDisplay>
768
769
770```yue
771-- 使用包含字段 "value" 的元表创建
772tb = <"value">: 123
773tb.<index> = tb.<>
774print tb.value
775tb.<> = __index: {item: "hello"}
776print tb.item
777```
778
779</YueDisplay>
780
781* **元表解构**
782使用被 **<>** 包围的元方法键解构元表。
783
784```yuescript
785{item, :new, :<close>, <index>: getter} = tb
786print item, new, close, getter
787```
788<YueDisplay>
789
790```yue
791{item, :new, :<close>, <index>: getter} = tb
792print item, new, close, getter
793```
794
795</YueDisplay>
796
797### 存在性
798
799**?** 运算符可以在多种上下文中用来检查存在性。
800
801```yuescript
802func?!
803print abc?["你好 世界"]?.xyz
804
805x = tab?.value
806len = utf8?.len or string?.len or (o) -> #o
807
808if print and x?
809 print x
810
811with? io.open "test.txt", "w"
812 \write "你好"
813 \close!
814```
815<YueDisplay>
816
817```yue
818func?!
819print abc?["你好 世界"]?.xyz
820
821x = tab?.value
822len = utf8?.len or string?.len or (o) -> #o
823
824if print and x?
825 print x
826
827with? io.open "test.txt", "w"
828 \write "你好"
829 \close!
830```
831
832</YueDisplay>
833
834### 管道
835
836与其使用一系列嵌套的函数调用,你还可以考虑使用运算符 **|>** 来传递值。
837
838```yuescript
839"你好" |> print
8401 |> print 2 -- 将管道项作为第一个参数插入
8412 |> print 1, _, 3 -- 带有占位符的管道
842
843-- 多行的管道表达式
844readFile "example.txt"
845 |> extract language, {}
846 |> parse language
847 |> emit
848 |> render
849 |> print
850```
851<YueDisplay>
852
853```yue
854"你好" |> print
8551 |> print 2 -- 将管道项作为第一个参数插入
8562 |> print 1, _, 3 -- 带有占位符的管道
857-- 多行的管道表达式
858readFile "example.txt"
859 |> extract language, {}
860 |> parse language
861 |> emit
862 |> render
863 |> print
864```
865
866</YueDisplay>
867
868### 空值合并
869
870如果其左操作数不是 **nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非 nil 的值,**??** 运算符将不再计算其右操作数。
871```yuescript
872local a, b, c, d
873a = b ?? c ?? d
874func a ?? {}
875
876a ??= false
877```
878<YueDisplay>
879
880```yue
881local a, b, c, d
882a = b ?? c ?? d
883func a ?? {}
884a ??= false
885```
886
887</YueDisplay>
888
889### 隐式对象
890
891你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。
892
893```yuescript
894-- 赋值时使用隐式对象
895list =
896 * 1
897 * 2
898 * 3
899
900-- 函数调用时使用隐式对象
901func
902 * 1
903 * 2
904 * 3
905
906-- 返回时使用隐式对象
907f = ->
908 return
909 * 1
910 * 2
911 * 3
912
913-- 表格时使用隐式对象
914tb =
915 name: "abc"
916
917 values:
918 - "a"
919 - "b"
920 - "c"
921
922 objects:
923 - name: "a"
924 value: 1
925 func: => @value + 1
926 tb:
927 fieldA: 1
928
929 - name: "b"
930 value: 2
931 func: => @value + 2
932 tb: { }
933```
934<YueDisplay>
935
936```yue
937-- 赋值时使用隐式对象
938list =
939 * 1
940 * 2
941 * 3
942
943-- 函数调用时使用隐式对象
944func
945 * 1
946 * 2
947 * 3
948
949-- 返回时使用隐式对象
950f = ->
951 return
952 * 1
953 * 2
954 * 3
955
956-- 表格时使用隐式对象
957tb =
958 name: "abc"
959
960 values:
961 - "a"
962 - "b"
963 - "c"
964
965 objects:
966 - name: "a"
967 value: 1
968 func: => @value + 1
969 tb:
970 fieldA: 1
971
972 - name: "b"
973 value: 2
974 func: => @value + 2
975 tb: { }
976```
977
978</YueDisplay>
979
980## 模块
981
982### 导入
983
984导入语句是一个语法糖,用于需要引入一个模块或者从已导入的模块中提取子项目。从模块导入的变量默认为不可修改的常量。
985
986```yuescript
987-- 用作表解构
988do
989 import insert, concat from table
990 -- 当给 insert, concat 变量赋值时,编译器会报告错误
991 import C, Ct, Cmt from require "lpeg"
992 -- 快捷写法引入模块的子项
993 import x, y, z from 'mymodule'
994 -- 使用Python风格的导入
995 from 'module' import a, b, c
996
997-- 快捷地导入一个模块
998do
999 import 'module'
1000 import 'module_x'
1001 import "d-a-s-h-e-s"
1002 import "module.part"
1003
1004-- 导入模块后起一个别名使用,或是进行导入模块表的解构
1005do
1006 import "player" as PlayerModule
1007 import "lpeg" as :C, :Ct, :Cmt
1008 import "export" as {one, two, Something:{umm:{ch}}}
1009```
1010<YueDisplay>
1011
1012```yue
1013-- 用作表解构
1014do
1015 import insert, concat from table
1016 -- 当给 insert, concat 变量赋值时,编译器会报告错误
1017 import C, Ct, Cmt from require "lpeg"
1018 -- 快捷写法引入模块的子项
1019 import x, y, z from 'mymodule'
1020 -- 使用Python风格的导入
1021 from 'module' import a, b, c
1022
1023-- 快捷地导入一个模块
1024do
1025 import 'module'
1026 import 'module_x'
1027 import "d-a-s-h-e-s"
1028 import "module.part"
1029
1030-- 导入模块后起一个别名使用,或是进行导入模块表的解构
1031do
1032 import "player" as PlayerModule
1033 import "lpeg" as :C, :Ct, :Cmt
1034 import "export" as {one, two, Something:{umm:{ch}}}
1035```
1036
1037</YueDisplay>
1038
1039### 导入全局变量
1040
1041你可以使用 `import` 将指定的全局变量导入到本地变量中。当导入一系列对全局变量的链式访问时,最后一个访问的字段将被赋值给本地变量。
1042
1043```yuescript
1044do
1045 import tostring
1046 import table.concat
1047 print concat ["a", tostring 1]
1048```
1049<YueDisplay>
1050
1051```yue
1052do
1053 import tostring
1054 import table.concat
1055 print concat ["a", tostring 1]
1056```
1057
1058</YueDisplay>
1059
1060#### 自动导入
1061
1062在一个代码块的顶部写 `import global`,会将当前作用域中尚未显式声明或赋值过的变量名,自动导入为本地常量,并在该语句的位置绑定到同名的全局变量。
1063
1064但是在同一作用域中被显式声明为全局的变量不会被自动导入,因此可以继续进行赋值操作。
1065
1066```yuescript
1067do
1068 import global
1069 print "hello"
1070 math.random 3
1071 -- print = nil -- 报错:自动导入的全局变量为常量
1072
1073do
1074 -- 被显式声明为全局的变量不会被自动导入
1075 import global
1076 global FLAG
1077 print FLAG
1078 FLAG = 123
1079```
1080<YueDisplay>
1081
1082```yue
1083do
1084 import global
1085 print "hello"
1086 math.random 3
1087 -- print = nil -- 报错:自动导入的全局变量是常量
1088
1089do
1090 -- 被显式声明为全局的变量不会被自动导入
1091 import global
1092 global FLAG
1093 print FLAG
1094 FLAG = 123
1095```
1096
1097</YueDisplay>
1098
1099### 导出
1100
1101导出语句提供了一种简洁的方式来定义当前的模块。
1102
1103* **命名导出**
1104带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。
1105
1106```yuescript
1107export a, b, c = 1, 2, 3
1108export cool = "cat"
1109
1110export What = if this
1111 "abc"
1112else
1113 "def"
1114
1115export y = ->
1116 hallo = 3434
1117
1118export class Something
1119 umm: "cool"
1120```
1121<YueDisplay>
1122
1123```yue
1124export a, b, c = 1, 2, 3
1125export cool = "cat"
1126
1127export What = if this
1128 "abc"
1129else
1130 "def"
1131
1132export y = ->
1133 hallo = 3434
1134
1135export class Something
1136 umm: "cool"
1137```
1138
1139</YueDisplay>
1140
1141使用解构进行命名导出。
1142
1143```yuescript
1144export :loadstring, to_lua: tolua = yue
1145export {itemA: {:fieldA = '默认值'}} = tb
1146```
1147<YueDisplay>
1148
1149```yue
1150export :loadstring, to_lua: tolua = yue
1151export {itemA: {:fieldA = '默认值'}} = tb
1152```
1153
1154</YueDisplay>
1155
1156从模块导出命名项目时,可以不用创建局部变量。
1157
1158```yuescript
1159export.itemA = tb
1160export.<index> = items
1161export["a-b-c"] = 123
1162```
1163<YueDisplay>
1164
1165```yue
1166export.itemA = tb
1167export.<index> = items
1168export["a-b-c"] = 123
1169```
1170
1171</YueDisplay>
1172
1173* **未命名导出**
1174未命名导出会将要导出的目标项目添加到导出表的数组部分。
1175
1176```yuescript
1177d, e, f = 3, 2, 1
1178export d, e, f
1179
1180export if this
1181 123
1182else
1183 456
1184
1185export with tmp
1186 j = 2000
1187```
1188<YueDisplay>
1189
1190```yue
1191d, e, f = 3, 2, 1
1192export d, e, f
1193
1194export if this
1195 123
1196else
1197 456
1198
1199export with tmp
1200 j = 2000
1201```
1202
1203</YueDisplay>
1204
1205* **默认导出**
1206在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。
1207
1208```yuescript
1209export default ->
1210 print "你好"
1211 123
1212```
1213<YueDisplay>
1214
1215```yue
1216export default ->
1217 print "你好"
1218 123
1219```
1220
1221</YueDisplay>
1222
1223## 赋值
1224
1225月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过 **local** 和 **global** 声明来改变声明变量的作用范围。
1226
1227```yuescript
1228hello = "world"
1229a, b, c = 1, 2, 3
1230hello = 123 -- 访问现有的变量
1231```
1232<YueDisplay>
1233
1234```yue
1235hello = "world"
1236a, b, c = 1, 2, 3
1237hello = 123 -- 访问现有的变量
1238```
1239
1240</YueDisplay>
1241
1242### 执行更新
1243
1244你可以使用各式二进制运算符执行更新赋值。
1245```yuescript
1246x = 1
1247x += 1
1248x -= 1
1249x *= 10
1250x /= 10
1251x %= 10
1252s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量
1253arg or= "默认值"
1254```
1255<YueDisplay>
1256
1257```yue
1258x = 1
1259x += 1
1260x -= 1
1261x *= 10
1262x /= 10
1263x %= 10
1264s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量
1265arg or= "默认值"
1266```
1267
1268</YueDisplay>
1269
1270### 链式赋值
1271
1272你可以进行链式赋值,将多个项目赋予相同的值。
1273```yuescript
1274a = b = c = d = e = 0
1275x = y = z = f!
1276```
1277<YueDisplay>
1278
1279```yue
1280a = b = c = d = e = 0
1281x = y = z = f!
1282```
1283
1284</YueDisplay>
1285
1286### 显式声明局部变量
1287```yuescript
1288do
1289 local a = 1
1290 local *
1291 print "预先声明后续所有变量为局部变量"
1292 x = -> 1 + y + z
1293 y, z = 2, 3
1294 global instance = Item\new!
1295
1296do
1297 local X = 1
1298 local ^
1299 print "只预先声明后续大写的变量为局部变量"
1300 a = 1
1301 B = 2
1302```
1303<YueDisplay>
1304
1305```yue
1306do
1307 local a = 1
1308 local *
1309 print "预先声明后续所有变量为局部变量"
1310 x = -> 1 + y + z
1311 y, z = 2, 3
1312 global instance = Item\new!
1313
1314do
1315 local X = 1
1316 local ^
1317 print "只预先声明后续大写的变量为局部变量"
1318 a = 1
1319 B = 2
1320```
1321
1322</YueDisplay>
1323
1324### 显式声明全局变量
1325```yuescript
1326do
1327 global a = 1
1328 global *
1329 print "预先声明所有变量为全局变量"
1330 x = -> 1 + y + z
1331 y, z = 2, 3
1332
1333do
1334 global x = 1
1335 global ^
1336 print "只预先声明大写的变量为全局变量"
1337 a = 1
1338 B = 2
1339 local Temp = "一个局部值"
1340```
1341<YueDisplay>
1342
1343```yue
1344do
1345 global a = 1
1346 global *
1347 print "预先声明所有变量为全局变量"
1348 x = -> 1 + y + z
1349 y, z = 2, 3
1350
1351do
1352 global x = 1
1353 global ^
1354 print "只预先声明大写的变量为全局变量"
1355 a = 1
1356 B = 2
1357 local Temp = "一个局部值"
1358```
1359
1360</YueDisplay>
1361
1362## 解构赋值
1363
1364解构赋值是一种快速从 Lua 表中按名称或基于数组中的位置提取值的方法。
1365
1366通常当你看到一个字面量的 Lua 表,比如 `{1,2,3}`,它位于赋值的右侧,因为它是一个值。解构赋值语句的写法就是交换了字面量 Lua 表的角色,并将其放在赋值语句的左侧。
1367
1368最好是通过示例来解释。以下是如何从表格中解包前两个值的方法:
1369
1370```yuescript
1371thing = [1, 2]
1372
1373[a, b] = thing
1374print a, b
1375```
1376<YueDisplay>
1377
1378
1379```yue
1380thing = [1, 2]
1381
1382[a, b] = thing
1383print a, b
1384```
1385
1386</YueDisplay>
1387
1388在解构表格字面量中,键代表从右侧读取的键,值代表读取的值将被赋予的名称。
1389
1390```yuescript
1391obj = {
1392 hello: "world"
1393 day: "tuesday"
1394 length: 20
1395}
1396
1397{hello: hello, day: the_day} = obj
1398print hello, the_day
1399
1400:day = obj -- 可以不带大括号进行简单的解构
1401```
1402<YueDisplay>
1403
1404```yue
1405obj = {
1406 hello: "world"
1407 day: "tuesday"
1408 length: 20
1409}
1410
1411{hello: hello, day: the_day} = obj
1412print hello, the_day
1413
1414:day = obj -- 可以不带大括号进行简单的解构
1415```
1416
1417</YueDisplay>
1418
1419这也适用于嵌套的数据结构:
1420
1421```yuescript
1422obj2 = {
1423 numbers: [1,2,3,4]
1424 properties: {
1425 color: "green"
1426 height: 13.5
1427 }
1428}
1429
1430{numbers: [first, second], properties: {color: color}} = obj2
1431print first, second, color
1432```
1433<YueDisplay>
1434
1435```yue
1436obj2 = {
1437 numbers: [1,2,3,4]
1438 properties: {
1439 color: "green"
1440 height: 13.5
1441 }
1442}
1443
1444{numbers: [first, second]} = obj2
1445print first, second, color
1446```
1447
1448</YueDisplay>
1449
1450如果解构语句很复杂,也可以任意将其分散在几行中。稍微复杂一些的示例:
1451
1452```yuescript
1453{
1454 numbers: [first, second]
1455 properties: {
1456 color: color
1457 }
1458} = obj2
1459```
1460<YueDisplay>
1461
1462```yue
1463{
1464 numbers: [first, second]
1465 properties: {
1466 color: color
1467 }
1468} = obj2
1469```
1470
1471</YueDisplay>
1472
1473有时候我们会需要从 Lua 表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符:
1474
1475```yuescript
1476{:concat, :insert} = table
1477```
1478<YueDisplay>
1479
1480```yue
1481{:concat, :insert} = table
1482```
1483
1484</YueDisplay>
1485
1486这样的用法与导入语法有些相似。但我们可以通过混合语法重命名我们想要提取的字段:
1487
1488```yuescript
1489{:mix, :max, random: rand} = math
1490```
1491<YueDisplay>
1492
1493```yue
1494{:mix, :max, random: rand} = math
1495```
1496
1497</YueDisplay>
1498
1499在进行解构时,你可以指定默认值,如:
1500
1501```yuescript
1502{:name = "nameless", :job = "jobless"} = person
1503```
1504<YueDisplay>
1505
1506```yue
1507{:name = "nameless", :job = "jobless"} = person
1508```
1509
1510</YueDisplay>
1511
1512在进行列表解构时,你可以使用`_`作为占位符:
1513
1514```yuescript
1515[_, two, _, four] = items
1516```
1517<YueDisplay>
1518
1519```yue
1520[_, two, _, four] = items
1521```
1522
1523</YueDisplay>
1524
1525### 范围解构
1526
1527你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。
1528
1529```yuescript
1530orders = ["first", "second", "third", "fourth", "last"]
1531[first, ...bulk, last] = orders
1532print first -- 打印: first
1533print bulk -- 打印: {"second", "third", "fourth"}
1534print last -- 打印: last
1535```
1536<YueDisplay>
1537
1538```yue
1539orders = ["first", "second", "third", "fourth", "last"]
1540[first, ...bulk, last] = orders
1541print first -- 打印: first
1542print bulk -- 打印: {"second", "third", "fourth"}
1543print last -- 打印: last
1544```
1545
1546</YueDisplay>
1547
1548展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获:
1549
1550```yuescript
1551-- 捕获第一个元素之后的所有元素
1552[first, ...rest] = orders
1553
1554-- 捕获最后一个元素之前的所有元素
1555[...start, last] = orders
1556
1557-- 跳过中间的元素,只捕获第一个和最后一个元素
1558[first, ..._, last] = orders
1559```
1560<YueDisplay>
1561
1562```yue
1563-- 捕获第一个元素之后的所有元素
1564[first, ...rest] = orders
1565
1566-- 捕获最后一个元素之前的所有元素
1567[...start, last] = orders
1568
1569-- 跳过中间的元素,只捕获第一个和最后一个元素
1570[first, ..._, last] = orders
1571```
1572
1573</YueDisplay>
1574
1575### 在其它地方的解构赋值
1576
1577解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在 for 循环中:
1578
1579```yuescript
1580tuples = [
1581 ["hello", "world"]
1582 ["egg", "head"]
1583]
1584
1585for [left, right] in *tuples
1586 print left, right
1587```
1588<YueDisplay>
1589
1590```yue
1591tuples = [
1592 ["hello", "world"]
1593 ["egg", "head"]
1594]
1595
1596for [left, right] in *tuples
1597 print left, right
1598```
1599
1600</YueDisplay>
1601
1602我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在 for 语句的名称子句中使用解构来解包它。
1603
1604## If 赋值
1605
1606`if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。注意,你必须使用“海象运算符” `:=` 而不是 `=` 来做赋值。
1607
1608```yuescript
1609if user := database.find_user "moon"
1610 print user.name
1611```
1612<YueDisplay>
1613
1614```yue
1615if user := database.find_user "moon"
1616 print user.name
1617```
1618
1619</YueDisplay>
1620
1621```yuescript
1622if hello := os.getenv "hello"
1623 print "你有 hello", hello
1624elseif world := os.getenv "world"
1625 print "你有 world", world
1626else
1627 print "什么都没有 :("
1628```
1629<YueDisplay>
1630
1631```yue
1632if hello := os.getenv "hello"
1633 print "你有 hello", hello
1634elseif world := os.getenv "world"
1635 print "你有 world", world
1636else
1637 print "什么都没有 :("
1638```
1639
1640</YueDisplay>
1641
1642使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。
1643```yuescript
1644if success, result := pcall -> "无报错地获取结果"
1645 print result -- 变量 result 是有作用域的
1646print "好的"
1647```
1648<YueDisplay>
1649
1650```yue
1651if success, result := pcall -> "无报错地获取结果"
1652 print result -- 变量 result 是有作用域的
1653print "好的"
1654```
1655
1656</YueDisplay>
1657
1658### While 赋值
1659
1660你可以在 while 循环中同样使用赋值来获取循环条件的值。
1661```yuescript
1662while byte := stream\read_one!
1663 -- 对 byte 做一些操作
1664 print byte
1665```
1666<YueDisplay>
1667
1668```yue
1669while byte := stream\read_one!
1670 -- 对 byte 做一些操作
1671 print byte
1672```
1673
1674</YueDisplay>
1675
1676## 可变参数赋值
1677
1678你可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用 Lua 的方式访问其内容。
1679```yuescript
1680list = [1, 2, 3, 4, 5]
1681fn = (ok) -> ok, table.unpack list
1682ok, ... = fn true
1683count = select '#', ...
1684first = select 1, ...
1685print ok, count, first
1686```
1687<YueDisplay>
1688
1689```yue
1690list = [1, 2, 3, 4, 5]
1691fn = (ok) -> ok, table.unpack list
1692ok, ... = fn true
1693count = select '#', ...
1694first = select 1, ...
1695print ok, count, first
1696```
1697
1698</YueDisplay>
1699
1700## 空白
1701
1702月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。
1703
1704### 语句分隔符
1705
1706一条语句通常以换行结束。你也可以使用分号 `;` 显式结束一条语句,从而在同一行中编写多条语句:
1707
1708```yuescript
1709a = 1; b = 2; print a + b
1710```
1711<YueDisplay>
1712
1713```yue
1714a = 1; b = 2; print a + b
1715```
1716
1717</YueDisplay>
1718
1719### 多行链式调用
1720
1721你可以使用相同的缩进来编写多行链式函数调用。
1722```yuescript
1723Rx.Observable
1724 .fromRange 1, 8
1725 \filter (x) -> x % 2 == 0
1726 \concat Rx.Observable.of 'who do we appreciate'
1727 \map (value) -> value .. '!'
1728 \subscribe print
1729```
1730<YueDisplay>
1731
1732```yue
1733Rx.Observable
1734 .fromRange 1, 8
1735 \filter (x) -> x % 2 == 0
1736 \concat Rx.Observable.of 'who do we appreciate'
1737 \map (value) -> value .. '!'
1738 \subscribe print
1739```
1740
1741</YueDisplay>
1742
1743## 注释
1744
1745```yuescript
1746-- 我是一个注释
1747
1748str = --[[
1749这是一个多行注释。
1750没问题。
1751]] strA \ -- 注释 1
1752 .. strB \ -- 注释 2
1753 .. strC
1754
1755func --[[端口]] 3000, --[[ip]] "192.168.1.1"
1756```
1757<YueDisplay>
1758
1759```yue
1760-- 我是一个注释
1761
1762str = --[[
1763这是一个多行注释。
1764没问题。
1765]] strA \ -- 注释 1
1766 .. strB \ -- 注释 2
1767 .. strC
1768
1769func --[[端口]] 3000, --[[ip]] "192.168.1.1"
1770```
1771
1772</YueDisplay>
1773
1774## 错误处理
1775
1776用于统一进行 Lua 错误处理的便捷语法。
1777
1778```yuescript
1779try
1780 func 1, 2, 3
1781catch err
1782 print yue.traceback err
1783
1784success, result = try
1785 func 1, 2, 3
1786catch err
1787 yue.traceback err
1788
1789try func 1, 2, 3
1790catch err
1791 print yue.traceback err
1792
1793success, result = try func 1, 2, 3
1794
1795try
1796 print "尝试中"
1797 func 1, 2, 3
1798
1799-- 使用if赋值模式
1800if success, result := try func 1, 2, 3
1801catch err
1802 print yue.traceback err
1803 print result
1804```
1805<YueDisplay>
1806
1807```yue
1808try
1809 func 1, 2, 3
1810catch err
1811 print yue.traceback err
1812
1813success, result = try
1814 func 1, 2, 3
1815catch err
1816 yue.traceback err
1817
1818try func 1, 2, 3
1819catch err
1820 print yue.traceback err
1821
1822success, result = try func 1, 2, 3
1823
1824try
1825 print "尝试中"
1826 func 1, 2, 3
1827
1828-- 使用if赋值模式
1829if success, result := try func 1, 2, 3
1830catch err
1831 print yue.traceback err
1832 print result
1833```
1834
1835</YueDisplay>
1836
1837### 错误处理简化
1838
1839`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。
1840
1841```yuescript
1842a, b, c = try? func!
1843
1844-- 与空值合并运算符一起使用
1845a = (try? func!) ?? "default"
1846
1847-- 作为函数参数
1848f try? func!
1849
1850-- 带 catch 块的 try!
1851f try?
1852 print 123
1853 func!
1854catch e
1855 print e
1856 e
1857```
1858<YueDisplay>
1859
1860```yue
1861a, b, c = try? func!
1862
1863-- 与空值合并运算符一起使用
1864a = (try? func!) ?? "default"
1865
1866-- 作为函数参数
1867f try? func!
1868
1869-- 带 catch 块的 try!
1870f try?
1871 print 123
1872 func!
1873catch e
1874 print e
1875 e
1876```
1877
1878</YueDisplay>
1879
1880## 属性
1881
1882月之脚本现在提供了 Lua 5.4 新增的叫做属性的语法支持。在月之脚本编译到的 Lua 目标版本低于 5.4 时,你仍然可以同时使用`const` 和 `close` 的属性声明语法,并获得常量检查和作用域回调的功能。
1883
1884```yuescript
1885const a = 123
1886close _ = <close>: -> print "超出范围。"
1887```
1888<YueDisplay>
1889
1890```yue
1891const a = 123
1892close _ = <close>: -> print "超出范围。"
1893```
1894
1895</YueDisplay>
1896
1897你可以对进行解构得到的变量标记为常量。
1898
1899```yuescript
1900const {:a, :b, c, d} = tb
1901-- a = 1
1902```
1903<YueDisplay>
1904
1905```yue
1906const {:a, :b, c, d} = tb
1907-- a = 1
1908```
1909
1910</YueDisplay>
1911
1912你也可以声明全局变量为常量。
1913
1914```yuescript
1915global const Constant = 123
1916-- Constant = 1
1917```
1918<YueDisplay>
1919
1920```yue
1921global const Constant = 123
1922-- Constant = 1
1923```
1924
1925</YueDisplay>
1926
1927## 字面量
1928
1929Lua 中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和 **nil**。
1930
1931但与 Lua 不同的是,单引号和双引号字符串内部允许有换行:
1932
1933```yuescript
1934some_string = "这是一个字符串
1935 并包括一个换行。"
1936
1937-- 使用#{}语法可以将表达式插入到字符串字面量中。
1938-- 字符串插值只在双引号字符串中可用。
1939print "我有#{math.random! * 100}%的把握。"
1940```
1941<YueDisplay>
1942
1943```yue
1944some_string = "这是一个字符串
1945 并包括一个换行。"
1946
1947-- 使用#{}语法可以将表达式插入到字符串字面量中。
1948-- 字符串插值只在双引号字符串中可用。
1949print "我有#{math.random! * 100}%的把握。"
1950```
1951
1952</YueDisplay>
1953
1954### 数字字面量
1955
1956你可以在数字字面量中使用下划线来增加可读性。
1957
1958```yuescript
1959integer = 1_000_000
1960hex = 0xEF_BB_BF
1961binary = 0B10011
1962```
1963<YueDisplay>
1964
1965
1966```yue
1967integer = 1_000_000
1968hex = 0xEF_BB_BF
1969binary = 0B10011
1970```
1971
1972</YueDisplay>
1973
1974### YAML 风格字符串
1975
1976使用 `|` 前缀标记一个多行 YAML 风格字符串:
1977
1978```yuescript
1979str = |
1980 key: value
1981 list:
1982 - item1
1983 - #{expr}
1984```
1985<YueDisplay>
1986
1987```yue
1988str = |
1989 key: value
1990 list:
1991 - item1
1992 - #{expr}
1993```
1994
1995</YueDisplay>
1996
1997其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。
1998
1999YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。
2000
2001```yuescript
2002fn = ->
2003 str = |
2004 foo:
2005 bar: baz
2006 return str
2007```
2008<YueDisplay>
2009
2010```yue
2011fn = ->
2012 str = |
2013 foo:
2014 bar: baz
2015 return str
2016```
2017
2018</YueDisplay>
2019
2020输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。
2021
2022支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义:
2023
2024```yuescript
2025str = |
2026 path: "C:\Program Files\App"
2027 note: 'He said: "#{Hello}!"'
2028```
2029<YueDisplay>
2030
2031```yue
2032str = |
2033 path: "C:\Program Files\App"
2034 note: 'He said: "#{Hello}!"'
2035```
2036
2037</YueDisplay>
2038
2039## 函数字面量
2040
2041所有函数都是使用月之脚本的函数表达式创建的。一个简单的函数可以用箭头表示为:**->**。
2042
2043```yuescript
2044my_function = ->
2045my_function() -- 调用空函数
2046```
2047<YueDisplay>
2048
2049```yue
2050my_function = ->
2051my_function() -- 调用空函数
2052```
2053
2054</YueDisplay>
2055
2056函数体可以是紧跟在箭头后的一个语句,或者是在后面的行上使用同样缩进的一系列语句:
2057
2058```yuescript
2059func_a = -> print "你好,世界"
2060
2061func_b = ->
2062 value = 100
2063 print "这个值是:", value
2064```
2065<YueDisplay>
2066
2067```yue
2068func_a = -> print "你好,世界"
2069
2070func_b = ->
2071 value = 100
2072 print "这个值是:", value
2073```
2074
2075</YueDisplay>
2076
2077如果一个函数没有参数,可以使用 **\!** 操作符调用它,而不是空括号。使用 **\!** 调用没有参数的函数是推荐的写法。
2078
2079```yuescript
2080func_a!
2081func_b()
2082```
2083<YueDisplay>
2084
2085```yue
2086func_a!
2087func_b()
2088```
2089
2090</YueDisplay>
2091
2092带有参数的函数可以通过在箭头前加上括号中的参数名列表来进行创建:
2093
2094```yuescript
2095sum = (x, y) -> print "数字的和", x + y
2096```
2097<YueDisplay>
2098
2099```yue
2100sum = (x, y) -> print "数字的和", x + y
2101```
2102
2103</YueDisplay>
2104
2105函数可以通过在函数名后列出参数来调用。当对函数做嵌套的调用时,后面列出的参数会应用于左侧最近的函数。
2106
2107```yuescript
2108sum 10, 20
2109print sum 10, 20
2110
2111a b c "a", "b", "c"
2112```
2113<YueDisplay>
2114
2115```yue
2116sum 10, 20
2117print sum 10, 20
2118
2119a b c "a", "b", "c"
2120```
2121
2122</YueDisplay>
2123
2124为了避免在调用函数时产生歧义,也可以使用括号将参数括起来。比如在以下的例子中是必需的,这样才能确保参数被传入到正确的函数。
2125
2126```yuescript
2127print "x:", sum(10, 20), "y:", sum(30, 40)
2128```
2129<YueDisplay>
2130
2131```yue
2132print "x:", sum(10, 20), "y:", sum(30, 40)
2133```
2134
2135</YueDisplay>
2136
2137注意:函数名与开始括号之间不能有任何空格。
2138
2139函数会将函数体中的最后一个语句强制转换为返回语句,这被称作隐式返回:
2140
2141```yuescript
2142sum = (x, y) -> x + y
2143print "数字的和是", sum 10, 20
2144```
2145<YueDisplay>
2146
2147```yue
2148sum = (x, y) -> x + y
2149print "数字的和是", sum 10, 20
2150```
2151
2152</YueDisplay>
2153
2154如果你需要做显式返回,可以使用 return 关键字:
2155
2156```yuescript
2157sum = (x, y) -> return x + y
2158```
2159<YueDisplay>
2160
2161```yue
2162sum = (x, y) -> return x + y
2163```
2164
2165</YueDisplay>
2166
2167就像在Lua中一样,函数可以返回多个值。最后一个语句必须是由逗号分隔的值列表:
2168
2169```yuescript
2170mystery = (x, y) -> x + y, x - y
2171a, b = mystery 10, 20
2172```
2173<YueDisplay>
2174
2175```yue
2176mystery = (x, y) -> x + y, x - y
2177a, b = mystery 10, 20
2178```
2179
2180</YueDisplay>
2181
2182### 粗箭头
2183
2184因为在 Lua 中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含 self 参数的函数。
2185
2186```yuescript
2187func = (num) => @value + num
2188```
2189<YueDisplay>
2190
2191```yue
2192func = (num) => @value + num
2193```
2194
2195</YueDisplay>
2196
2197### 参数默认值
2198
2199可以为函数的参数提供默认值。如果参数的值为 nil,则确定该参数为空。任何具有默认值的 nil 参数在函数体运行之前都会被替换。
2200
2201```yuescript
2202my_function = (name = "某物", height = 100) ->
2203 print "你好,我是", name
2204 print "我的高度是", height
2205```
2206<YueDisplay>
2207
2208```yue
2209my_function = (name = "某物", height = 100) ->
2210 print "你好,我是", name
2211 print "我的高度是", height
2212```
2213
2214</YueDisplay>
2215
2216函数参数的默认值表达式在函数体中会按参数声明的顺序进行计算。因此,在默认值的表达式中可以访问先前声明的参数。
2217
2218```yuescript
2219some_args = (x = 100, y = x + 1000) ->
2220 print x + y
2221```
2222<YueDisplay>
2223
2224```yue
2225some_args = (x = 100, y = x + 1000) ->
2226 print x + y
2227```
2228
2229</YueDisplay>
2230
2231### 多行参数
2232
2233当调用接收大量参数的函数时,将参数列表分成多行是很方便的。由于月之脚本语言对空白字符的敏感性,做参数列表的分割时务必要小心。
2234
2235如果要将参数列表写到下一行,那么当前行必须以逗号结束。并且下一行的缩进必须比当前的缩进多。一旦做了参数的缩进,所有其他参数列表的行必须保持相同的缩进级别,以成为参数列表的一部分。
2236
2237```yuescript
2238my_func 5, 4, 3,
2239 8, 9, 10
2240
2241cool_func 1, 2,
2242 3, 4,
2243 5, 6,
2244 7, 8
2245```
2246<YueDisplay>
2247
2248```yue
2249my_func 5, 4, 3,
2250 8, 9, 10
2251
2252cool_func 1, 2,
2253 3, 4,
2254 5, 6,
2255 7, 8
2256```
2257
2258</YueDisplay>
2259
2260这种调用方式可以做嵌套。并通过缩进级别来确定参数属于哪一个函数。
2261
2262```yuescript
2263my_func 5, 6, 7,
2264 6, another_func 6, 7, 8,
2265 9, 1, 2,
2266 5, 4
2267```
2268<YueDisplay>
2269
2270```yue
2271my_func 5, 6, 7,
2272 6, another_func 6, 7, 8,
2273 9, 1, 2,
2274 5, 4
2275```
2276
2277</YueDisplay>
2278
2279因为 Lua 表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是 Lua 表的一部分。
2280
2281```yuescript
2282x = [
2283 1, 2, 3, 4, a_func 4, 5,
2284 5, 6,
2285 8, 9, 10
2286]
2287```
2288<YueDisplay>
2289
2290```yue
2291x = [
2292 1, 2, 3, 4, a_func 4, 5,
2293 5, 6,
2294 8, 9, 10
2295]
2296```
2297
2298</YueDisplay>
2299
2300有个不常见的写法可以注意一下,如果我们将在后面使用较低的缩进,我们可以为函数参数提供更深的缩进来区分列表的归属。
2301
2302```yuescript
2303y = [ my_func 1, 2, 3,
2304 4, 5,
2305 5, 6, 7
2306]
2307```
2308<YueDisplay>
2309
2310```yue
2311y = [ my_func 1, 2, 3,
2312 4, 5,
2313 5, 6, 7
2314]
2315```
2316
2317</YueDisplay>
2318
2319对于其它有代码块跟随的语句,比如条件语句,也可以通过小心安排缩进来做类似的事。比如我们可以通过调整缩进级别来控制一些值归属于哪个语句:
2320
2321```yuescript
2322if func 1, 2, 3,
2323 "你好",
2324 "世界"
2325 print "你好"
2326 print "我在if内部"
2327
2328if func 1, 2, 3,
2329 "你好",
2330 "世界"
2331 print "hello"
2332 print "我在if内部"
2333```
2334<YueDisplay>
2335
2336```yue
2337if func 1, 2, 3,
2338 "你好",
2339 "世界"
2340 print "你好"
2341 print "我在if内部"
2342
2343if func 1, 2, 3,
2344 "你好",
2345 "世界"
2346 print "你好"
2347 print "我在if内部"
2348```
2349
2350</YueDisplay>
2351
2352### 参数解构
2353
2354月之脚本支持在函数形参位置对传入对象进行解构。适用两类解构表子面量:
2355
2356- 使用 {} 包裹的字面量/对象形参,支持提供获得空字段时的默认值(例如 {:a, :b}、{a: a1 = 123})。
2357
2358- 无 {} 包裹、以键值/简写键序列开头,直至遇到其它表达式终止(例如 :a, b: b1, :c),表示从同一个对象中解构多个字段。
2359
2360```yuescript
2361f1 = (:a, :b, :c) ->
2362 print a, b, c
2363
2364f1 a: 1, b: "2", c: {}
2365
2366f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2367 print a1, b, c
2368
2369arg1 = {a: 0}
2370f2 arg1, arg2
2371```
2372<YueDisplay>
2373
2374```yue
2375f1 = (:a, :b, :c) ->
2376 print a, b, c
2377
2378f1 a: 1, b: "2", c: {}
2379
2380f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2381 print a1, b, c
2382
2383arg1 = {a: 0}
2384f2 arg1, arg2
2385```
2386
2387</YueDisplay>
2388
2389### 前置返回表达式
2390
2391在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下:
2392
2393```yuescript
2394findFirstEven = (list): nil ->
2395 for item in *list
2396 if type(item) == "table"
2397 for sub in *item
2398 if sub % 2 == 0
2399 return sub
2400```
2401<YueDisplay>
2402
2403```yue
2404findFirstEven = (list): nil ->
2405 for item in *list
2406 if type(item) == "table"
2407 for sub in *item
2408 if sub % 2 == 0
2409 return sub
2410```
2411
2412</YueDisplay>
2413
2414这个写法等价于:
2415
2416```yuescript
2417findFirstEven = (list) ->
2418 for item in *list
2419 if type(item) == "table"
2420 for sub in *item
2421 if sub % 2 == 0
2422 return sub
2423 nil
2424```
2425<YueDisplay>
2426
2427```yue
2428findFirstEven = (list) ->
2429 for item in *list
2430 if type(item) == "table"
2431 for sub in *item
2432 if sub % 2 == 0
2433 return sub
2434 nil
2435```
2436
2437</YueDisplay>
2438
2439唯一的区别在于:你可以将函数的返回值表达式提前写在 `->` 或 `=>` 前,用以指示该函数应隐式返回该表达式的值。这样即使在多层循环或条件判断的场景下,也无需编写尾行悬挂的返回表达式,逻辑结构会更加直观清晰。
2440
2441### 命名变长参数
2442
2443你可以使用 `(...t) ->` 语法来将变长参数自动存储到一个命名表中。这个表会包含所有传入的参数(包括 `nil` 值),并且会在表的 `n` 字段中存储实际传入的参数个数(包括 `nil` 值在内的个数)。
2444
2445```yuescript
2446f = (...t) ->
2447 print "参数个数:", t.n
2448 print "表长度:", #t
2449 for i = 1, t.n
2450 print t[i]
2451
2452f 1, 2, 3
2453f "a", "b", "c", "d"
2454f!
2455
2456-- 处理包含 nil 的情况
2457process = (...args) ->
2458 sum = 0
2459 for i = 1, args.n
2460 if args[i] != nil and type(args[i]) == "number"
2461 sum += args[i]
2462 sum
2463
2464process 1, nil, 3, nil, 5
2465```
2466<YueDisplay>
2467
2468```yue
2469f = (...t) ->
2470 print "参数个数:", t.n
2471 print "表长度:", #t
2472 for i = 1, t.n
2473 print t[i]
2474
2475f 1, 2, 3
2476f "a", "b", "c", "d"
2477f!
2478
2479-- 处理包含 nil 的情况
2480process = (...args) ->
2481 sum = 0
2482 for i = 1, args.n
2483 if args[i] != nil and type(args[i]) == "number"
2484 sum += args[i]
2485 sum
2486
2487process 1, nil, 3, nil, 5
2488```
2489
2490</YueDisplay>
2491
2492## 反向回调
2493
2494反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。
2495
2496```yuescript
2497<- f
2498print "hello"
2499```
2500<YueDisplay>
2501
2502```yue
2503<- f
2504print "hello"
2505```
2506
2507</YueDisplay>
2508
2509月之脚本也提供了粗箭头反向回调函数。
2510
2511```yuescript
2512<= f
2513print @value
2514```
2515<YueDisplay>
2516
2517```yue
2518<= f
2519print @value
2520```
2521
2522</YueDisplay>
2523
2524你可以通过一个占位符指定回调函数的传参位置。
2525
2526```yuescript
2527(x) <- map _, [1, 2, 3]
2528x * 2
2529```
2530<YueDisplay>
2531
2532```yue
2533(x) <- map _, [1, 2, 3]
2534x * 2
2535```
2536
2537</YueDisplay>
2538
2539如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。
2540
2541```yuescript
2542result, msg = do
2543 data <- readAsync "文件名.txt"
2544 print data
2545 info <- processAsync data
2546 check info
2547print result, msg
2548```
2549<YueDisplay>
2550
2551```yue
2552result, msg = do
2553 data <- readAsync "文件名.txt"
2554 print data
2555 info <- processAsync data
2556 check info
2557print result, msg
2558```
2559
2560</YueDisplay>
2561
2562## 表格字面量
2563
2564和 Lua 一样,表格可以通过花括号进行定义。
2565
2566```yuescript
2567some_values = [1, 2, 3, 4]
2568```
2569<YueDisplay>
2570
2571```yue
2572some_values = [1, 2, 3, 4]
2573```
2574
2575</YueDisplay>
2576
2577但与Lua不同的是,给表格中的键赋值是用 **:**(而不是 **=**)。
2578
2579```yuescript
2580some_values = {
2581 name: "Bill",
2582 age: 200,
2583 ["favorite food"]: "rice"
2584}
2585```
2586<YueDisplay>
2587
2588```yue
2589some_values = {
2590 name: "Bill",
2591 age: 200,
2592 ["favorite food"]: "rice"
2593}
2594```
2595
2596</YueDisplay>
2597
2598如果只分配一个键值对的表格,可以省略花括号。
2599
2600```yuescript
2601profile =
2602 height: "4英尺",
2603 shoe_size: 13,
2604 favorite_foods: ["冰淇淋", "甜甜圈"]
2605```
2606<YueDisplay>
2607
2608```yue
2609profile =
2610 height: "4英尺",
2611 shoe_size: 13,
2612 favorite_foods: ["冰淇淋", "甜甜圈"]
2613```
2614
2615</YueDisplay>
2616
2617可以使用换行符而不使用逗号(或两者都用)来分隔表格中的值:
2618
2619```yuescript
2620values = {
2621 1, 2, 3, 4
2622 5, 6, 7, 8
2623 name: "超人"
2624 occupation: "打击犯罪"
2625}
2626```
2627<YueDisplay>
2628
2629```yue
2630values = {
2631 1, 2, 3, 4
2632 5, 6, 7, 8
2633 name: "超人"
2634 occupation: "打击犯罪"
2635}
2636```
2637
2638</YueDisplay>
2639
2640创建单行表格字面量时,也可以省略花括号:
2641
2642```yuescript
2643my_function dance: "探戈", partner: "无"
2644
2645y = type: "狗", legs: 4, tails: 1
2646```
2647<YueDisplay>
2648
2649```yue
2650my_function dance: "探戈", partner: "无"
2651
2652y = type: "狗", legs: 4, tails: 1
2653```
2654
2655</YueDisplay>
2656
2657表格字面量的键可以使用 Lua 语言的关键字,而无需转义:
2658
2659```yuescript
2660tbl = {
2661 do: "某事"
2662 end: "饥饿"
2663}
2664```
2665<YueDisplay>
2666
2667```yue
2668tbl = {
2669 do: "某事"
2670 end: "饥饿"
2671}
2672```
2673
2674</YueDisplay>
2675
2676如果你要构造一个由变量组成的表,并希望键与变量名相同,那么可以使用 **:** 前缀操作符:
2677
2678```yuescript
2679hair = "金色"
2680height = 200
2681person = { :hair, :height, shoe_size: 40 }
2682
2683print_table :hair, :height
2684```
2685<YueDisplay>
2686
2687```yue
2688hair = "金色"
2689height = 200
2690person = { :hair, :height, shoe_size: 40 }
2691
2692print_table :hair, :height
2693```
2694
2695</YueDisplay>
2696
2697如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在 Lua 中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。
2698
2699```yuescript
2700t = {
2701 [1 + 2]: "你好"
2702 "你好 世界": true
2703}
2704```
2705<YueDisplay>
2706
2707```yue
2708t = {
2709 [1 + 2]: "你好"
2710 "你好 世界": true
2711}
2712```
2713
2714</YueDisplay>
2715
2716Lua 的表同时具有数组部分和哈希部分,但有时候你会希望在书写 Lua 表时,对 Lua 表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。
2717
2718```yuescript
2719some_values = [ 1, 2, 3, 4 ]
2720list_with_one_element = [ 1, ]
2721```
2722<YueDisplay>
2723
2724```yue
2725some_values = [ 1, 2, 3, 4 ]
2726list_with_one_element = [ 1, ]
2727```
2728
2729</YueDisplay>
2730
2731## 推导式
2732
2733推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生 Lua 表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许你在每次遍历时设置新表格的键和值。
2734
2735### 列表推导式
2736
2737以下操作创建了一个 items 表的副本,但所有包含的值都翻倍了。
2738
2739```yuescript
2740items = [1, 2, 3, 4]
2741doubled = [item * 2 for i, item in ipairs items]
2742```
2743<YueDisplay>
2744
2745```yue
2746items = [1, 2, 3, 4]
2747doubled = [item * 2 for i, item in ipairs items]
2748```
2749
2750</YueDisplay>
2751
2752可以使用 `when` 子句筛选新表中包含的项目:
2753
2754```yuescript
2755slice = [item for i, item in ipairs items when i > 1 and i < 3]
2756```
2757<YueDisplay>
2758
2759```yue
2760slice = [item for i, item in ipairs items when i > 1 and i < 3]
2761```
2762
2763</YueDisplay>
2764
2765因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled 示例可以重写为:
2766
2767```yuescript
2768doubled = [item * 2 for item in *items]
2769```
2770<YueDisplay>
2771
2772```yue
2773doubled = [item * 2 for item in *items]
2774```
2775
2776</YueDisplay>
2777
2778在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理:
2779
2780```yuescript
2781data =
2782 a: [1, 2, 3]
2783 b: [4, 5, 6]
2784
2785flat = [...v for k,v in pairs data]
2786-- flat 现在为 [1, 2, 3, 4, 5, 6]
2787```
2788<YueDisplay>
2789
2790```yue
2791data =
2792 a: [1, 2, 3]
2793 b: [4, 5, 6]
2794
2795flat = [...v for k,v in pairs data]
2796-- flat 现在为 [1, 2, 3, 4, 5, 6]
2797```
2798
2799</YueDisplay>
2800
2801for 和 when 子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个 for 子句。
2802
2803使用多个 for 子句与使用多重循环的效果相同:
2804
2805```yuescript
2806x_coords = [4, 5, 6, 7]
2807y_coords = [9, 2, 3]
2808
2809points = [ [x, y] for x in *x_coords \
2810for y in *y_coords]
2811```
2812<YueDisplay>
2813
2814```yue
2815x_coords = [4, 5, 6, 7]
2816y_coords = [9, 2, 3]
2817
2818points = [ [x, y] for x in *x_coords \
2819for y in *y_coords]
2820```
2821
2822</YueDisplay>
2823
2824在推导式中也可以使用简单的数值 for 循环:
2825
2826```yuescript
2827evens = [i for i = 1, 100 when i % 2 == 0]
2828```
2829<YueDisplay>
2830
2831```yue
2832evens = [i for i = 1, 100 when i % 2 == 0]
2833```
2834
2835</YueDisplay>
2836
2837### 表格推导式
2838
2839表格推导式和列表推导式的语法非常相似,只是要使用 **{** 和 **}** 并从每次迭代中取两个值。
2840
2841以下示例生成了表格 thing 的副本:
2842
2843```yuescript
2844thing = {
2845 color: "red"
2846 name: "fast"
2847 width: 123
2848}
2849
2850thing_copy = {k, v for k, v in pairs thing}
2851```
2852<YueDisplay>
2853
2854```yue
2855thing = {
2856 color: "red"
2857 name: "fast"
2858 width: 123
2859}
2860
2861thing_copy = {k, v for k, v in pairs thing}
2862```
2863
2864</YueDisplay>
2865
2866```yuescript
2867no_color = {k, v for k, v in pairs thing when k != "color"}
2868```
2869<YueDisplay>
2870
2871```yue
2872no_color = {k, v for k, v in pairs thing when k != "color"}
2873```
2874
2875</YueDisplay>
2876
2877**\*** 操作符在表格推导式中能使用。在下面的例子里,我们为几个数字创建了一个平方根查找表。
2878
2879```yuescript
2880numbers = [1, 2, 3, 4]
2881sqrts = {i, math.sqrt i for i in *numbers}
2882```
2883<YueDisplay>
2884
2885```yue
2886numbers = [1, 2, 3, 4]
2887sqrts = {i, math.sqrt i for i in *numbers}
2888```
2889
2890</YueDisplay>
2891
2892表格推导式中的键值元组也可以来自单个表达式,在这种情况下,表达式在计算后应返回两个值。第一个用作键,第二个用作值:
2893
2894在下面的示例中,我们将一些数组转换为一个表,其中每个数组里的第一项是键,第二项是值。
2895
2896```yuescript
2897tuples = [ ["hello", "world"], ["foo", "bar"]]
2898tbl = {unpack tuple for tuple in *tuples}
2899```
2900<YueDisplay>
2901
2902```yue
2903tuples = [ ["hello", "world"], ["foo", "bar"]]
2904tbl = {unpack tuple for tuple in *tuples}
2905```
2906
2907</YueDisplay>
2908
2909### 切片
2910
2911当使用 **\*** 操作符时,月之脚本还提供了一种特殊的语法来限制要遍历的列表范围。这个语法也相当于在 for 循环中设置迭代边界和步长。
2912
2913下面的案例中,我们在切片中设置最小和最大边界,取索引在 1 到 5 之间(包括 1 和 5)的所有项目:
2914
2915```yuescript
2916slice = [item for item in *items[1, 5]]
2917```
2918<YueDisplay>
2919
2920```yue
2921slice = [item for item in *items[1, 5]]
2922```
2923
2924</YueDisplay>
2925
2926切片的任意参数都可以省略,并会使用默认值。在如下示例中,如果省略了最大索引边界,它默认为表的长度。使下面的代码取除第一个元素之外的所有元素:
2927
2928```yuescript
2929slice = [item for item in *items[2,]]
2930```
2931<YueDisplay>
2932
2933```yue
2934slice = [item for item in *items[2,]]
2935```
2936
2937</YueDisplay>
2938
2939如果省略了最小边界,便默认会设置为 1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …)
2940
2941```yuescript
2942slice = [item for item in *items[,,2]]
2943```
2944<YueDisplay>
2945
2946
2947```yue
2948slice = [item for item in *items[,,2]]
2949```
2950
2951</YueDisplay>
2952
2953最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。
2954
2955```yuescript
2956-- 取最后4个元素
2957slice = [item for item in *items[-4,-1]]
2958```
2959<YueDisplay>
2960
2961```yue
2962-- 取最后4个元素
2963slice = [item for item in *items[-4,-1]]
2964```
2965
2966</YueDisplay>
2967
2968切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。
2969
2970```yuescript
2971reverse_slice = [item for item in *items[-1,1,-1]]
2972```
2973<YueDisplay>
2974
2975```yue
2976reverse_slice = [item for item in *items[-1,1,-1]]
2977```
2978
2979</YueDisplay>
2980
2981#### 切片表达式
2982
2983切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。
2984
2985```yuescript
2986-- 取第2和第4个元素作为新的列表
2987sub_list = items[2, 4]
2988```
2989<YueDisplay>
2990
2991```yue
2992-- 取第2和第4个元素作为新的列表
2993sub_list = items[2, 4]
2994```
2995
2996</YueDisplay>
2997
2998## for 循环
2999
3000Lua 中有两种 for 循环形式,数字型和通用型:
3001
3002```yuescript
3003for i = 10, 20
3004 print i
3005
3006for k = 1, 15, 2 -- 提供了一个遍历的步长
3007 print k
3008
3009for key, value in pairs object
3010 print key, value
3011```
3012<YueDisplay>
3013
3014```yue
3015for i = 10, 20
3016 print i
3017
3018for k = 1, 15, 2 -- 提供了一个遍历的步长
3019 print k
3020
3021for key, value in pairs object
3022 print key, value
3023```
3024
3025</YueDisplay>
3026
3027可以使用切片和 **\*** 操作符,就像在列表推导中一样:
3028
3029```yuescript
3030for item in *items[2, 4]
3031 print item
3032```
3033<YueDisplay>
3034
3035```yue
3036for item in *items[2, 4]
3037 print item
3038```
3039
3040</YueDisplay>
3041
3042当代码语句只有一行时,循环语句也都可以写作更短的语法:
3043
3044```yuescript
3045for item in *items do print item
3046
3047for j = 1, 10, 3 do print j
3048```
3049<YueDisplay>
3050
3051```yue
3052for item in *items do print item
3053
3054for j = 1, 10, 3 do print j
3055```
3056
3057</YueDisplay>
3058
3059for 循环也可以用作表达式。for 循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。
3060
3061将每个偶数加倍:
3062
3063```yuescript
3064doubled_evens = for i = 1, 20
3065 if i % 2 == 0
3066 i * 2
3067 else
3068 i
3069```
3070<YueDisplay>
3071
3072```yue
3073doubled_evens = for i = 1, 20
3074 if i % 2 == 0
3075 i * 2
3076 else
3077 i
3078```
3079
3080</YueDisplay>
3081
3082此外,for 循环还支持带返回值的 break 语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。
3083
3084例如,查找第一个大于 10 的数字:
3085
3086```yuescript
3087first_large = for n in *numbers
3088 break n if n > 10
3089```
3090<YueDisplay>
3091
3092```yue
3093first_large = for n in *numbers
3094 break n if n > 10
3095```
3096
3097</YueDisplay>
3098
3099你还可以结合 for 循环表达式与 continue 语句来过滤值。
3100
3101注意出现在函数体末尾的 for 循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回 nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加 for 循环表达式。
3102
3103```yuescript
3104func_a = -> for i = 1, 10 do print i
3105func_b = -> return for i = 1, 10 do i
3106
3107print func_a! -- 打印 nil
3108print func_b! -- 打印 table 对象
3109```
3110<YueDisplay>
3111
3112```yue
3113func_a = -> for i = 1, 10 do print i
3114func_b = -> return for i = 1, 10 do i
3115
3116print func_a! -- 打印 nil
3117print func_b! -- 打印 table 对象
3118```
3119
3120</YueDisplay>
3121
3122这样做是为了避免在不需要返回循环结果的函数,创建无效的返回值表格。
3123
3124## repeat 循环
3125
3126repeat 循环是从 Lua 语言中搬过来的相似语法:
3127
3128```yuescript
3129i = 10
3130repeat
3131 print i
3132 i -= 1
3133until i == 0
3134```
3135<YueDisplay>
3136
3137```yue
3138i = 10
3139repeat
3140 print i
3141 i -= 1
3142until i == 0
3143```
3144
3145</YueDisplay>
3146
3147## while 循环
3148
3149在月之脚本中的 while 循环有四种写法:
3150
3151```yuescript
3152i = 10
3153while i > 0
3154 print i
3155 i -= 1
3156
3157while running == true do my_function!
3158```
3159<YueDisplay>
3160
3161```yue
3162i = 10
3163while i > 0
3164 print i
3165 i -= 1
3166
3167while running == true do my_function!
3168```
3169
3170</YueDisplay>
3171
3172```yuescript
3173i = 10
3174until i == 0
3175 print i
3176 i -= 1
3177
3178until running == false do my_function!
3179```
3180<YueDisplay>
3181
3182```yue
3183i = 10
3184until i == 0
3185 print i
3186 i -= 1
3187until running == false do my_function!
3188```
3189
3190</YueDisplay>
3191
3192像 for 循环的语法一样,while 循环也可以作为一个表达式使用。为了使函数返回 while 循环的累积列表值,必须明确使用返回语句返回 while 循环表达式。
3193
3194## 继续
3195
3196继续语句可以用来跳出当前的循环迭代。
3197
3198```yuescript
3199i = 0
3200while i < 10
3201 i += 1
3202 continue if i % 2 == 0
3203 print i
3204```
3205<YueDisplay>
3206
3207```yue
3208i = 0
3209while i < 10
3210 i += 1
3211 continue if i % 2 == 0
3212 print i
3213```
3214
3215</YueDisplay>
3216
3217继续语句也可以与各种循环表达式一起使用,以防止当前的循环迭代结果累积到结果列表中。以下示例将数组表过滤为仅包含偶数的数组:
3218
3219```yuescript
3220my_numbers = [1, 2, 3, 4, 5, 6]
3221odds = for x in *my_numbers
3222 continue if x % 2 == 1
3223 x
3224```
3225<YueDisplay>
3226
3227```yue
3228my_numbers = [1, 2, 3, 4, 5, 6]
3229odds = for x in *my_numbers
3230 continue if x % 2 == 1
3231 x
3232```
3233
3234</YueDisplay>
3235
3236## 条件语句
3237
3238```yuescript
3239have_coins = false
3240if have_coins
3241 print "有硬币"
3242else
3243 print "没有硬币"
3244```
3245<YueDisplay>
3246
3247```yue
3248have_coins = false
3249if have_coins
3250 print "有硬币"
3251else
3252 print "没有硬币"
3253```
3254
3255</YueDisplay>
3256
3257对于简单的语句,也可以使用简短的语法:
3258
3259```yuescript
3260have_coins = false
3261if have_coins then print "有硬币" else print "没有硬币"
3262```
3263<YueDisplay>
3264
3265```yue
3266have_coins = false
3267if have_coins then print "有硬币" else print "没有硬币"
3268```
3269
3270</YueDisplay>
3271
3272因为if语句可以用作表达式,所以也可以这样写:
3273
3274```yuescript
3275have_coins = false
3276print if have_coins then "有硬币" else "没有硬币"
3277```
3278<YueDisplay>
3279
3280```yue
3281have_coins = false
3282print if have_coins then "有硬币" else "没有硬币"
3283```
3284
3285</YueDisplay>
3286
3287条件语句也可以作为表达式用在返回语句和赋值语句中:
3288
3289```yuescript
3290is_tall = (name) ->
3291 if name == "Rob"
3292 true
3293 else
3294 false
3295
3296message = if is_tall "Rob"
3297 "我很高"
3298else
3299 "我不是很高"
3300
3301print message -- 打印: 我很高
3302```
3303<YueDisplay>
3304
3305```yue
3306is_tall = (name) ->
3307 if name == "Rob"
3308 true
3309 else
3310 false
3311
3312message = if is_tall "Rob"
3313 "我很高"
3314else
3315 "我不是很高"
3316
3317print message -- 打印: 我很高
3318```
3319
3320</YueDisplay>
3321
3322if 的反义词是 unless(相当于 if not,正如“如果”对应“除非”):
3323
3324```yuescript
3325unless os.date("%A") == "Monday"
3326 print "今天不是星期一!"
3327```
3328<YueDisplay>
3329
3330
3331```yue
3332unless os.date("%A") == "Monday"
3333 print "今天不是星期一!"
3334```
3335
3336</YueDisplay>
3337
3338```yuescript
3339print "你真幸运!" unless math.random! > 0.1
3340```
3341<YueDisplay>
3342
3343```yue
3344print "你真幸运!" unless math.random! > 0.1
3345```
3346
3347</YueDisplay>
3348
3349### 范围表达式
3350
3351你可以使用范围表达式来编写进行范围检查的代码。
3352
3353```yuescript
3354a = 5
3355
3356if a in [1, 3, 5, 7]
3357 print "检查离散值的相等性"
3358
3359if a in list
3360 print "检查`a`是否在列表中"
3361```
3362<YueDisplay>
3363
3364```yue
3365a = 5
3366
3367if a in [1, 3, 5, 7]
3368 print "检查离散值的相等性"
3369
3370if a in list
3371 print "检查`a`是否在列表中"
3372```
3373
3374</YueDisplay>
3375
3376```yuescript
3377print "你很幸运!" unless math.random! > 0.1
3378```
3379<YueDisplay>
3380
3381```yue
3382print "你很幸运!" unless math.random! > 0.1
3383```
3384
3385</YueDisplay>
3386
3387## 代码行修饰符
3388
3389为了方便编写代码,循环语句和 if 语句可以应用于单行代码语句的末尾:
3390
3391```yuescript
3392print "你好,世界" if name == "Rob"
3393```
3394<YueDisplay>
3395
3396```yue
3397print "你好,世界" if name == "Rob"
3398```
3399
3400</YueDisplay>
3401
3402修饰 for 循环的示例:
3403
3404```yuescript
3405print "项目: ", item for item in *items
3406```
3407<YueDisplay>
3408
3409```yue
3410print "项目: ", item for item in *items
3411```
3412
3413</YueDisplay>
3414
3415修饰 while 循环的示例:
3416
3417```yuescript
3418game\update! while game\isRunning!
3419
3420reader\parse_line! until reader\eof!
3421```
3422<YueDisplay>
3423
3424```yue
3425game\update! while game\isRunning!
3426
3427reader\parse_line! until reader\eof!
3428```
3429
3430</YueDisplay>
3431
3432## switch 语句
3433
3434switch 语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和 if 语句一样,switch 语句在最后可以接一个 else 代码块来处理没有匹配的情况。在生成的 Lua 代码中,进行比较是使用 == 操作符完成的。switch 语句中也可以使用赋值表达式来储存临时变量值。
3435
3436```yuescript
3437switch name := "Dan"
3438 when "Robert"
3439 print "你是Robert"
3440 when "Dan", "Daniel"
3441 print "你的名字是Dan"
3442 else
3443 print "我不认识你,你的名字是#{name}"
3444```
3445<YueDisplay>
3446
3447```yue
3448switch name := "Dan"
3449 when "Robert"
3450 print "你是Robert"
3451 when "Dan", "Daniel"
3452 print "你的名字是Dan"
3453 else
3454 print "我不认识你,你的名字是#{name}"
3455```
3456
3457</YueDisplay>
3458
3459switch 语句的 when 子句中可以通过使用逗号分隔的列表来匹配多个值。
3460
3461switch 语句也可以作为表达式使用,下面我们可以将 switch 语句返回的结果分配给一个变量:
3462
3463```yuescript
3464b = 1
3465next_number = switch b
3466 when 1
3467 2
3468 when 2
3469 3
3470 else
3471 error "数字数得太大了!"
3472```
3473<YueDisplay>
3474
3475```yue
3476b = 1
3477next_number = switch b
3478 when 1
3479 2
3480 when 2
3481 3
3482 else
3483 error "数字数得太大了!"
3484```
3485
3486</YueDisplay>
3487
3488我们可以使用 then 关键字在 when 子句的同一行上编写处理代码。else 代码块的后续代码中要写在同一行上不需要额外的关键字。
3489
3490```yuescript
3491msg = switch math.random(1, 5)
3492 when 1 then "你很幸运"
3493 when 2 then "你差点很幸运"
3494 else "不太幸运"
3495```
3496<YueDisplay>
3497
3498```yue
3499msg = switch math.random(1, 5)
3500 when 1 then "你很幸运"
3501 when 2 then "你差点很幸运"
3502 else "不太幸运"
3503```
3504
3505</YueDisplay>
3506
3507如果在编写 switch 语句时希望少写一个缩进,那么你可以把第一个 when 子句放在 switch 开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。
3508
3509```yuescript
3510switch math.random(1, 5)
3511 when 1
3512 print "你很幸运" -- 两个缩进级别
3513 else
3514 print "不太幸运"
3515
3516switch math.random(1, 5) when 1
3517 print "你很幸运" -- 一个缩进级别
3518else
3519 print "不太幸运"
3520```
3521<YueDisplay>
3522
3523```yue
3524switch math.random(1, 5)
3525 when 1
3526 print "你很幸运" -- 两个缩进级别
3527 else
3528 print "不太幸运"
3529
3530switch math.random(1, 5) when 1
3531 print "你很幸运" -- 一个缩进级别
3532else
3533 print "不太幸运"
3534```
3535
3536</YueDisplay>
3537
3538值得注意的是,在生成 Lua 代码时,我们要做检查的目标变量会放在 == 表达式的右侧。当你希望给 when 子句的比较对象定义一个 \_\_eq 元方法来重载判断逻辑时,可能会有用。
3539
3540### 表格匹配
3541
3542在 switch 的 when 子句中,如果期待检查目标是一个表格,且可以通过特定的结构进行解构并获得非 nil 值,那么你可以尝试使用表格匹配的语法。
3543
3544```yuescript
3545items =
3546 * x: 100
3547 y: 200
3548 * width: 300
3549 height: 400
3550
3551for item in *items
3552 switch item
3553 when :x, :y
3554 print "Vec2 #{x}, #{y}"
3555 when :width, :height
3556 print "尺寸 #{width}, #{height}"
3557```
3558<YueDisplay>
3559
3560```yue
3561items =
3562 * x: 100
3563 y: 200
3564 * width: 300
3565 height: 400
3566
3567for item in *items
3568 switch item
3569 when :x, :y
3570 print "Vec2 #{x}, #{y}"
3571 when :width, :height
3572 print "尺寸 #{width}, #{height}"
3573```
3574
3575</YueDisplay>
3576
3577你可以使用默认值来选择性地解构表格的某些字段。
3578
3579```yuescript
3580item = {}
3581
3582{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos')
3583
3584switch item
3585 when {pos: {:x = 50, :y = 200}}
3586 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过
3587```
3588<YueDisplay>
3589
3590```yue
3591item = {}
3592
3593{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos')
3594
3595switch item
3596 when {pos: {:x = 50, :y = 200}}
3597 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过
3598```
3599
3600</YueDisplay>
3601
3602你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。
3603
3604匹配数组元素。
3605
3606```yuescript
3607switch tb
3608 when [1, 2, 3]
3609 print "1, 2, 3"
3610 when [1, b, 3]
3611 print "1, #{b}, 3"
3612 when [1, 2, b = 3] -- 变量b有默认值
3613 print "1, 2, #{b}"
3614```
3615<YueDisplay>
3616
3617```yue
3618switch tb
3619 when [1, 2, 3]
3620 print "1, 2, 3"
3621 when [1, b, 3]
3622 print "1, #{b}, 3"
3623 when [1, 2, b = 3] -- 变量b有默认值
3624 print "1, 2, #{b}"
3625```
3626
3627</YueDisplay>
3628
3629匹配表格字段。
3630
3631```yuescript
3632switch tb
3633 when success: true, :result
3634 print "成功", result
3635 when success: false
3636 print "失败", result
3637 else
3638 print "无效值"
3639```
3640<YueDisplay>
3641
3642```yue
3643switch tb
3644 when success: true, :result
3645 print "成功", result
3646 when success: false
3647 print "失败", result
3648 else
3649 print "无效值"
3650```
3651
3652</YueDisplay>
3653
3654匹配嵌套的表格结构。
3655
3656```yuescript
3657switch tb
3658 when data: {type: "success", :content}
3659 print "成功", content
3660 when data: {type: "error", :content}
3661 print "失败", content
3662 else
3663 print "无效值"
3664```
3665<YueDisplay>
3666
3667```yue
3668switch tb
3669 when data: {type: "success", :content}
3670 print "成功", content
3671 when data: {type: "error", :content}
3672 print "失败", content
3673 else
3674 print "无效值"
3675```
3676
3677</YueDisplay>
3678
3679匹配表格数组。
3680
3681```yuescript
3682switch tb
3683 when [
3684 {a: 1, b: 2}
3685 {a: 3, b: 4}
3686 {a: 5, b: 6}
3687 fourth
3688 ]
3689 print "匹配成功", fourth
3690```
3691<YueDisplay>
3692
3693```yue
3694switch tb
3695 when [
3696 {a: 1, b: 2}
3697 {a: 3, b: 4}
3698 {a: 5, b: 6}
3699 fourth
3700 ]
3701 print "匹配成功", fourth
3702```
3703
3704</YueDisplay>
3705
3706匹配一个列表并捕获特定范围内的元素。
3707
3708```yuescript
3709segments = ["admin", "users", "logs", "view"]
3710switch segments
3711 when [...groups, resource, action]
3712 print "Group:", groups -- 打印: {"admin", "users"}
3713 print "Resource:", resource -- 打印: "logs"
3714 print "Action:", action -- 打印: "view"
3715```
3716<YueDisplay>
3717
3718```yue
3719segments = ["admin", "users", "logs", "view"]
3720switch segments
3721 when [...groups, resource, action]
3722 print "Group:", groups -- 打印: {"admin", "users"}
3723 print "Resource:", resource -- 打印: "logs"
3724 print "Action:", action -- 打印: "view"
3725```
3726
3727</YueDisplay>
3728
3729## 面向对象编程
3730
3731在以下的示例中,月之脚本生成的 Lua 代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果你想知道关于面向对象功能的实现细节,再查看 Lua 代码。
3732
3733一个简单的类:
3734
3735```yuescript
3736class Inventory
3737 new: =>
3738 @items = {}
3739
3740 add_item: (name) =>
3741 if @items[name]
3742 @items[name] += 1
3743 else
3744 @items[name] = 1
3745```
3746<YueDisplay>
3747
3748```yue
3749class Inventory
3750 new: =>
3751 @items = {}
3752
3753 add_item: (name) =>
3754 if @items[name]
3755 @items[name] += 1
3756 else
3757 @items[name] = 1
3758```
3759
3760</YueDisplay>
3761
3762在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合 Lua 表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为 “new” 的成员扮演了一个重要的角色,是作为构造函数来使用。
3763
3764值得注意的是,类中的方法都采用了粗箭头函数语法。当在类的实例上调用方法时,该实例会自动作为第一个参数被传入,因此粗箭头函数用于生成一个名为 “self” 的参数。
3765
3766此外,“@” 前缀在变量名上起到了简化作用,代表 “self”。例如,`@items` 就等同于 `self.items`。
3767
3768为了创建类的一个新实例,可以将类名当作一个函数来调用,这样就可以生成并返回一个新的实例。
3769
3770```yuescript
3771inv = Inventory!
3772inv\add_item "t-shirt"
3773inv\add_item "pants"
3774```
3775<YueDisplay>
3776
3777
3778```yue
3779inv = Inventory!
3780inv\add_item "t-shirt"
3781inv\add_item "pants"
3782```
3783
3784</YueDisplay>
3785
3786在月之脚本的类中,由于需要将类的实例作为参数传入到调用的方法中,因此使用了 **\\** 操作符做类的成员函数调用。
3787
3788需要特别注意的是,类的所有属性在其实例之间是共享的。这对于函数类型的成员属性通常不会造成问题,但对于其他类型的属性,可能会导致意外的结果。
3789
3790例如,在下面的示例中,clothes 属性在所有实例之间共享。因此,对这个属性在一个实例中的修改,将会影响到其他所有实例。
3791
3792```yuescript
3793class Person
3794 clothes: []
3795 give_item: (name) =>
3796 table.insert @clothes, name
3797
3798a = Person!
3799b = Person!
3800
3801a\give_item "pants"
3802b\give_item "shirt"
3803
3804-- 会同时打印出裤子和衬衫
3805print item for item in *a.clothes
3806```
3807<YueDisplay>
3808
3809```yue
3810class Person
3811 clothes: []
3812 give_item: (name) =>
3813 table.insert @clothes, name
3814
3815a = Person!
3816b = Person!
3817
3818a\give_item "pants"
3819b\give_item "shirt"
3820
3821-- 会同时打印出裤子和衬衫
3822print item for item in *a.clothes
3823```
3824
3825</YueDisplay>
3826
3827避免这个问题的正确方法是在构造函数中创建对象的可变状态:
3828
3829```yuescript
3830class Person
3831 new: =>
3832 @clothes = []
3833```
3834<YueDisplay>
3835
3836```yue
3837class Person
3838 new: =>
3839 @clothes = []
3840```
3841
3842</YueDisplay>
3843
3844### 继承
3845
3846`extends` 关键字可以在类声明中使用,以继承另一个类的属性和方法。
3847
3848```yuescript
3849class BackPack extends Inventory
3850 size: 10
3851 add_item: (name) =>
3852 if #@items > size then error "背包已满"
3853 super name
3854```
3855<YueDisplay>
3856
3857```yue
3858class BackPack extends Inventory
3859 size: 10
3860 add_item: (name) =>
3861 if #@items > size then error "背包已满"
3862 super name
3863```
3864
3865</YueDisplay>
3866
3867
3868在这一部分,我们对月之脚本中的 `Inventory` 类进行了扩展,加入了对可以携带物品数量的限制。
3869
3870在这个特定的例子中,子类并没有定义自己的构造函数。因此,当创建一个新的实例时,系统会默认调用父类的构造函数。但如果我们在子类中定义了构造函数,我们可以利用 `super` 方法来调用并执行父类的构造函数。
3871
3872此外,当一个类继承自另一个类时,它会尝试调用父类上的 `__inherited` 方法(如果这个方法存在的话),以此来向父类发送通知。这个 `__inherited` 函数接受两个参数:被继承的父类和继承的子类。
3873
3874```yuescript
3875class Shelf
3876 @__inherited: (child) =>
3877 print @__name, "被", child.__name, "继承"
3878
3879-- 将打印: Shelf 被 Cupboard 继承
3880class Cupboard extends Shelf
3881```
3882<YueDisplay>
3883
3884```yue
3885class Shelf
3886 @__inherited: (child) =>
3887 print @__name, "被", child.__name, "继承"
3888
3889-- 将打印: Shelf 被 Cupboard 继承
3890class Cupboard extends Shelf
3891```
3892
3893</YueDisplay>
3894
3895### super 关键字
3896
3897`super` 是一个特别的关键字,它有两种不同的使用方式:既可以当作一个对象来看待,也可以像调用函数那样使用。它仅在类的内部使用时具有特殊的功能。
3898
3899当 `super` 被作为一个函数调用时,它将调用父类中与之同名的函数。此时,当前的 `self` 会自动作为第一个参数传递,正如上面提到的继承示例所展示的那样。
3900
3901在将 `super` 当作普通值使用时,它实际上是对父类对象的引用。通过这种方式,我们可以访问父类中可能被子类覆盖的值,就像访问任何普通对象一样。
3902
3903此外,当使用 `\` 操作符与 `super` 一起使用时,`self`将被插入为第一个参数,而不是使用 `super` 本身的值。而在使用`.`操作符来检索函数时,则会返回父类中的原始函数。
3904
3905下面是一些使用 `super` 的不同方法的示例:
3906
3907```yuescript
3908class MyClass extends ParentClass
3909 a_method: =>
3910 -- 以下效果相同:
3911 super "你好", "世界"
3912 super\a_method "你好", "世界"
3913 super.a_method self, "你好", "世界"
3914
3915 -- super 作为值等于父类:
3916 assert super == ParentClass
3917```
3918<YueDisplay>
3919
3920```yue
3921class MyClass extends ParentClass
3922 a_method: =>
3923 -- 以下效果相同:
3924 super "你好", "世界"
3925 super\a_method "你好", "世界"
3926 super.a_method self, "你好", "世界"
3927
3928 -- super 作为值等于父类:
3929 assert super == ParentClass
3930```
3931
3932</YueDisplay>
3933
3934**super** 也可以用在函数存根的左侧。唯一的主要区别是,生成的函数不是绑定到 super 的值,而是绑定到 self。
3935
3936### 类型
3937
3938每个类的实例都带有它的类型。这存储在特殊的 \_\_class 属性中。此属性会保存类对象。类对象是我们用来构建新实例的对象。我们还可以索引类对象以检索类方法和属性。
3939
3940```yuescript
3941b = BackPack!
3942assert b.__class == BackPack
3943
3944print BackPack.size -- 打印 10
3945```
3946<YueDisplay>
3947
3948```yue
3949b = BackPack!
3950assert b.__class == BackPack
3951
3952print BackPack.size -- 打印 10
3953```
3954
3955</YueDisplay>
3956
3957### 类对象
3958
3959
3960在月之脚本中,当我们编写类的定义语句时,实际上是在创建一个类对象。这个类对象被保存在一个与该类同名的变量中。
3961
3962类对象具有函数的特性,可以被调用来创建新的实例。这正是我们在之前示例中所展示的创建类实例的方式。
3963
3964一个类由两个表构成:类表本身和一个基表。基表作为所有实例的元表。在类声明中列出的所有属性都存放在基表中。
3965
3966如果在类对象的元表中找不到某个属性,系统会从基表中检索该属性。这就意味着我们可以直接从类本身访问到其方法和属性。
3967
3968需要特别注意的是,对类对象的赋值并不会影响到基表,因此这不是向实例添加新方法的正确方式。相反,需要直接修改基表。关于这点,可以参考下面的 “__base” 字段。
3969
3970此外,类对象包含几个特殊的属性:当类被声明时,类的名称会作为一个字符串存储在类对象的 “__name” 字段中。
3971
3972```yuescript
3973print BackPack.__name -- 打印 Backpack
3974```
3975<YueDisplay>
3976
3977```yue
3978print BackPack.__name -- 打印 Backpack
3979```
3980
3981</YueDisplay>
3982
3983基础对象被保存在一个名为 `__base` 的特殊表中。我们可以编辑这个表,以便为那些已经创建出来的实例和还未创建的实例增加新的功能。
3984
3985另外,如果一个类是从另一个类派生而来的,那么其父类对象则会被存储在名为 `__parent` 的地方。这种机制允许在类之间实现继承和功能扩展。
3986
3987### 类变量
3988
3989我们可以直接在类对象中创建变量,而不是在类的基对象中,通过在类声明中的属性名前使用 @。
3990
3991```yuescript
3992class Things
3993 @some_func: => print "Hello from", @__name
3994
3995Things\some_func!
3996
3997-- 类变量在实例中不可见
3998assert Things().some_func == nil
3999```
4000<YueDisplay>
4001
4002```yue
4003class Things
4004 @some_func: => print "Hello from", @__name
4005
4006Things\some_func!
4007
4008-- 类变量在实例中不可见
4009assert Things().some_func == nil
4010```
4011
4012</YueDisplay>
4013
4014在表达式中,我们可以使用 @@ 来访问存储在 `self.__class` 中的值。因此,`@@hello` 是 `self.__class.hello` 的简写。
4015
4016```yuescript
4017class Counter
4018 @count: 0
4019
4020 new: =>
4021 @@count += 1
4022
4023Counter!
4024Counter!
4025
4026print Counter.count -- 输出 2
4027```
4028<YueDisplay>
4029
4030```yue
4031class Counter
4032 @count: 0
4033
4034 new: =>
4035 @@count += 1
4036
4037Counter!
4038Counter!
4039
4040print Counter.count -- 输出 2
4041```
4042
4043</YueDisplay>
4044
4045@@ 的调用语义与 @ 类似。调用 @@ 时,会使用 Lua 的冒号语法将类作为第一个参数传入。
4046
4047```yuescript
4048@@hello 1,2,3,4
4049```
4050<YueDisplay>
4051
4052```yue
4053@@hello 1,2,3,4
4054```
4055
4056</YueDisplay>
4057
4058### 类声明语句
4059
4060在类声明的主体中,除了键/值对外,我们还可以编写普通的表达式。在这种类声明体中的普通代码的上下文中,self 等于类对象,而不是实例对象。
4061
4062以下是创建类变量的另一种方法:
4063
4064```yuescript
4065class Things
4066 @class_var = "hello world"
4067```
4068<YueDisplay>
4069
4070```yue
4071class Things
4072 @class_var = "hello world"
4073```
4074
4075</YueDisplay>
4076
4077这些表达式会在所有属性被添加到类的基对象后执行。
4078
4079在类的主体中声明的所有变量都会限制作用域只在类声明的范围。这对于放置只有类方法可以访问的私有值或辅助函数很方便:
4080
4081```yuescript
4082class MoreThings
4083 secret = 123
4084 log = (msg) -> print "LOG:", msg
4085
4086 some_method: =>
4087 log "hello world: " .. secret
4088```
4089<YueDisplay>
4090
4091```yue
4092class MoreThings
4093 secret = 123
4094 log = (msg) -> print "LOG:", msg
4095
4096 some_method: =>
4097 log "hello world: " .. secret
4098```
4099
4100</YueDisplay>
4101
4102### @ 和 @@ 值
4103
4104当 @ 和 @@ 前缀在一个名字前时,它们分别代表在 self 和 self.\_\_class 中访问的那个名字。
4105
4106如果它们单独使用,它们是 self 和 self.\_\_class 的别名。
4107
4108```yuescript
4109assert @ == self
4110assert @@ == self.__class
4111```
4112<YueDisplay>
4113
4114```yue
4115assert @ == self
4116assert @@ == self.__class
4117```
4118
4119</YueDisplay>
4120
4121例如,使用 @@ 从实例方法快速创建同一类的新实例的方法:
4122
4123```yuescript
4124some_instance_method = (...) => @@ ...
4125```
4126<YueDisplay>
4127
4128```yue
4129some_instance_method = (...) => @@ ...
4130```
4131
4132</YueDisplay>
4133
4134### 构造属性提升
4135
4136为了减少编写简单值对象定义的代码。你可以这样简单写一个类:
4137
4138```yuescript
4139class Something
4140 new: (@foo, @bar, @@biz, @@baz) =>
4141
4142-- 这是以下声明的简写形式
4143
4144class Something
4145 new: (foo, bar, biz, baz) =>
4146 @foo = foo
4147 @bar = bar
4148 @@biz = biz
4149 @@baz = baz
4150```
4151<YueDisplay>
4152
4153```yue
4154class Something
4155 new: (@foo, @bar, @@biz, @@baz) =>
4156
4157-- 这是以下声明的简写形式
4158
4159class Something
4160 new: (foo, bar, biz, baz) =>
4161 @foo = foo
4162 @bar = bar
4163 @@biz = biz
4164 @@baz = baz
4165```
4166
4167</YueDisplay>
4168
4169你也可以使用这种语法为一个函数初始化传入对象的字段。
4170
4171```yuescript
4172new = (@fieldA, @fieldB) => @
4173obj = new {}, 123, "abc"
4174print obj
4175```
4176<YueDisplay>
4177
4178```yue
4179new = (@fieldA, @fieldB) => @
4180obj = new {}, 123, "abc"
4181print obj
4182```
4183
4184</YueDisplay>
4185
4186### 类表达式
4187
4188类声明的语法也可以作为一个表达式使用,可以赋值给一个变量或者被返回语句返回。
4189
4190```yuescript
4191x = class Bucket
4192 drops: 0
4193 add_drop: => @drops += 1
4194```
4195<YueDisplay>
4196
4197```yue
4198x = class Bucket
4199 drops: 0
4200 add_drop: => @drops += 1
4201```
4202
4203</YueDisplay>
4204
4205### 匿名类
4206
4207声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name 属性将为 nil。如果出现在赋值语句中,赋值操作左侧的名称将代替 nil。
4208
4209```yuescript
4210BigBucket = class extends Bucket
4211 add_drop: => @drops += 10
4212
4213assert Bucket.__name == "BigBucket"
4214```
4215<YueDisplay>
4216
4217```yue
4218BigBucket = class extends Bucket
4219 add_drop: => @drops += 10
4220
4221assert Bucket.__name == "BigBucket"
4222```
4223
4224</YueDisplay>
4225
4226你甚至可以省略掉主体,这意味着你可以这样写一个空白的匿名类:
4227
4228```yuescript
4229x = class
4230```
4231<YueDisplay>
4232
4233```yue
4234x = class
4235```
4236
4237</YueDisplay>
4238
4239### 类混合
4240
4241你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。
4242
4243```yuescript
4244MyIndex = __index: var: 1
4245
4246class X using MyIndex
4247 func: =>
4248 print 123
4249
4250x = X!
4251print x.var
4252
4253class Y using X
4254
4255y = Y!
4256y\func!
4257
4258assert y.__class.__parent ~= X -- X 不是 Y 的父类
4259```
4260<YueDisplay>
4261
4262```yue
4263MyIndex = __index: var: 1
4264
4265class X using MyIndex
4266 func: =>
4267 print 123
4268
4269x = X!
4270print x.var
4271
4272class Y using X
4273
4274y = Y!
4275y\func!
4276
4277assert y.__class.__parent ~= X -- X 不是 Y 的父类
4278```
4279
4280</YueDisplay>
4281
4282## with 语句
4283
4284在编写 Lua 代码时,我们在创建对象后的常见操作是立即调用这个对象一系列操作函数并设置一系列属性。
4285
4286这导致在代码中多次重复引用对象的名称,增加了不必要的文本噪音。一个常见的解决方案是在创建对象时,在构造函数传入一个表,该表包含要覆盖设置的键和值的集合。这样做的缺点是该对象的构造函数必须支持这种初始化形式。
4287
4288with 块有助于简化编写这样的代码。在 with 块内,我们可以使用以 . 或 \ 开头的特殊语句,这些语句代表我们正在使用的对象的操作。
4289
4290例如,我们可以这样处理一个新创建的对象:
4291
4292```yuescript
4293with Person!
4294 .name = "Oswald"
4295 \add_relative my_dad
4296 \save!
4297 print .name
4298```
4299<YueDisplay>
4300
4301```yue
4302with Person!
4303 .name = "Oswald"
4304 \add_relative my_dad
4305 \save!
4306 print .name
4307```
4308
4309</YueDisplay>
4310
4311with 语句也可以用作一个表达式,并返回它的代码块正在处理的对象。
4312
4313```yuescript
4314file = with File "favorite_foods.txt"
4315 \set_encoding "utf8"
4316```
4317<YueDisplay>
4318
4319```yue
4320file = with File "favorite_foods.txt"
4321 \set_encoding "utf8"
4322```
4323
4324</YueDisplay>
4325
4326或者…
4327
4328```yuescript
4329create_person = (name, relatives) ->
4330 with Person!
4331 .name = name
4332 \add_relative relative for relative in *relatives
4333
4334me = create_person "Leaf", [dad, mother, sister]
4335```
4336<YueDisplay>
4337
4338```yue
4339create_person = (name, relatives) ->
4340 with Person!
4341 .name = name
4342 \add_relative relative for relative in *relatives
4343
4344me = create_person "Leaf", [dad, mother, sister]
4345```
4346
4347</YueDisplay>
4348
4349在此用法中,with 可以被视为K组合子(k-combinator)的一种特殊形式。
4350
4351如果你想给表达式另外起一个名称的话,with 语句中的表达式也可以是一个赋值语句。
4352
4353```yuescript
4354with str := "你好"
4355 print "原始:", str
4356 print "大写:", \upper!
4357```
4358<YueDisplay>
4359
4360```yue
4361with str := "你好"
4362 print "原始:", str
4363 print "大写:", \upper!
4364```
4365
4366</YueDisplay>
4367
4368你可以在 `with` 语句中使用 `[]` 访问特殊键。
4369
4370```yuescript
4371with tb
4372 [1] = 1
4373 print [2]
4374 with [abc]
4375 [3] = [2]\func!
4376 ["key-name"] = value
4377 [] = "abc" -- 追加到 "tb"
4378```
4379<YueDisplay>
4380
4381```yue
4382with tb
4383 [1] = 1
4384 print [2]
4385 with [abc]
4386 [3] = [2]\func!
4387 ["key-name"] = value
4388 [] = "abc" -- 追加到 "tb"
4389```
4390
4391</YueDisplay>
4392
4393`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。
4394
4395```yuescript
4396with? obj
4397 print obj.name
4398```
4399<YueDisplay>
4400
4401```yue
4402with? obj
4403 print obj.name
4404```
4405
4406</YueDisplay>
4407
4408## do 语句
4409
4410当用作语句时,do 语句的作用就像在 Lua 中差不多。
4411
4412```yuescript
4413do
4414 var = "hello"
4415 print var
4416print var -- 这里是nil
4417```
4418<YueDisplay>
4419
4420```yue
4421do
4422 var = "hello"
4423 print var
4424print var -- 这里是nil
4425```
4426
4427</YueDisplay>
4428
4429月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将 do 语句代码块的最后一个语句作为表达式返回的结果。
4430
4431```yuescript
4432counter = do
4433 i = 0
4434 ->
4435 i += 1
4436 i
4437
4438print counter!
4439print counter!
4440```
4441<YueDisplay>
4442
4443```yue
4444counter = do
4445 i = 0
4446 ->
4447 i += 1
4448 i
4449
4450print counter!
4451print counter!
4452```
4453
4454</YueDisplay>
4455
4456```yuescript
4457tbl = {
4458 key: do
4459 print "分配键值!"
4460 1234
4461}
4462```
4463<YueDisplay>
4464
4465```yue
4466tbl = {
4467 key: do
4468 print "分配键值!"
4469 1234
4470}
4471```
4472
4473</YueDisplay>
4474
4475## 函数存根
4476
4477在编程中,将对象的方法作为函数类型的值进行传递是一种常见做法,尤其是在将实例方法作为回调函数传递给其他函数的情形中。当目标函数需要将该对象作为其第一个参数时,我们需要找到一种方式将对象和函数绑定在一起,以便能够正确地调用该函数。
4478
4479函数存根(stub)语法提供了一种便捷的方法来创建一个新的闭包函数,这个函数将对象和原函数绑定在一起。这样,当调用这个新创建的函数时,它会在正确的对象上下文中执行原有的函数。
4480
4481这种语法类似于使用 \ 操作符调用实例方法的方式,区别在于,这里不需要在 \ 操作符后面附加参数列表。
4482
4483```yuescript
4484my_object = {
4485 value: 1000
4486 write: => print "值为:", @value
4487}
4488
4489run_callback = (func) ->
4490 print "运行回调..."
4491 func!
4492
4493-- 这样写不起作用:
4494-- 函数没有引用my_object
4495run_callback my_object.write
4496
4497-- 函数存根语法
4498-- 让我们把对象捆绑到一个新函数中
4499run_callback my_object\write
4500```
4501<YueDisplay>
4502
4503```yue
4504my_object = {
4505 value: 1000
4506 write: => print "值为:", @value
4507}
4508
4509run_callback = (func) ->
4510 print "运行回调..."
4511 func!
4512
4513-- 这样写不起作用:
4514-- 函数没有引用my_object
4515run_callback my_object.write
4516
4517-- 函数存根语法
4518-- 让我们把对象捆绑到一个新函数中
4519run_callback my_object\write
4520```
4521
4522</YueDisplay>
4523
4524## 使用 using 语句:防止破坏性赋值
4525
4526Lua 的变量作用域是降低代码复杂度的重要工具。然而,随着代码量的增加,维护这些变量可能变得更加困难。比如,看看下面的代码片段:
4527
4528```yuescript
4529i = 100
4530
4531-- 许多代码行...
4532
4533my_func = ->
4534 i = 10
4535 while i > 0
4536 print i
4537 i -= 1
4538
4539my_func!
4540
4541print i -- 将打印 0
4542```
4543<YueDisplay>
4544
4545```yue
4546i = 100
4547
4548-- 许多代码行...
4549
4550my_func = ->
4551 i = 10
4552 while i > 0
4553 print i
4554 i -= 1
4555
4556my_func!
4557
4558print i -- 将打印 0
4559```
4560
4561</YueDisplay>
4562
4563在 `my_func` 中,我们不小心覆盖了变量 `i` 的值。虽然在这个例子中这个问题很明显,但在一个庞大的或者是由多人共同维护的代码库中,很难追踪每个变量的声明情况。
4564
4565如果我们可以明确指出哪些变量是我们想在当前作用域内修改的,并且防止我们不小心更改了其他作用域中同名的变量,那将大有裨益。
4566
4567`using` 语句就是为此而生。`using nil` 确保函数内部的赋值不会意外地影响到外部作用域的变量。我们只需将 `using` 子句放在函数的参数列表之后;若函数没有参数,则直接放在括号内即可。
4568
4569```yuescript
4570i = 100
4571
4572my_func = (using nil) ->
4573 i = "hello" -- 这里创建了一个新的局部变量
4574
4575my_func!
4576print i -- 打印 100,i 没有受到影响
4577```
4578<YueDisplay>
4579
4580```yue
4581i = 100
4582
4583my_func = (using nil) ->
4584 i = "hello" -- 这里创建了一个新的局部变量
4585
4586my_func!
4587print i -- 打印 100,i 没有受到影响
4588```
4589
4590</YueDisplay>
4591
4592using子句中可以填写多个用逗号分隔名称。指定可以访问和修改的外部变量的名称:
4593
4594```yuescript
4595tmp = 1213
4596i, k = 100, 50
4597
4598my_func = (add using k, i) ->
4599 tmp = tmp + add -- 创建了一个新的局部tmp
4600 i += tmp
4601 k += tmp
4602
4603my_func(22)
4604print i, k -- 这些已经被更新
4605```
4606<YueDisplay>
4607
4608```yue
4609tmp = 1213
4610i, k = 100, 50
4611
4612my_func = (add using k, i) ->
4613 tmp = tmp + add -- 创建了一个新的局部tmp
4614 i += tmp
4615 k += tmp
4616
4617my_func(22)
4618print i, k -- 这些已经被更新
4619```
4620
4621</YueDisplay>
4622
4623## 月之脚本语言库
4624
4625使用 `require("yue")` 来访问。
4626
4627### yue
4628
4629**描述:**
4630
4631月之脚本语言库。
4632
4633#### version
4634
4635**类型:** 成员变量。
4636
4637**描述:**
4638
4639月之脚本版本。
4640
4641**签名:**
4642```lua
4643version: string
4644```
4645
4646#### dirsep
4647
4648**类型:** 成员变量。
4649
4650**描述:**
4651
4652当前平台的文件分隔符。
4653
4654**签名:**
4655```lua
4656dirsep: string
4657```
4658
4659#### yue_compiled
4660
4661**类型:** 成员变量。
4662
4663**描述:**
4664
4665编译模块代码缓存。
4666
4667**签名:**
4668```lua
4669yue_compiled: {string: string}
4670```
4671
4672#### to_lua
4673
4674**类型:** 函数。
4675
4676**描述:**
4677
4678月之脚本的编译函数。它将 YueScript 代码编译为 Lua 代码。
4679
4680**签名:**
4681```lua
4682to_lua: function(code: string, config?: Config):
4683 --[[codes]] string | nil,
4684 --[[error]] string | nil,
4685 --[[globals]] {{string, integer, integer}} | nil
4686```
4687
4688**参数:**
4689
4690| 参数名 | 类型 | 描述 |
4691| --- | --- | --- |
4692| code | string | YueScript 代码。 |
4693| config | Config | [可选] 编译器选项。 |
4694
4695**返回值:**
4696
4697| 返回类型 | 描述 |
4698| --- | --- |
4699| string \| nil | 编译后的 Lua 代码,如果编译失败则为 nil。 |
4700| string \| nil | 错误消息,如果编译成功则为 nil。 |
4701| {{string, integer, integer}} \| nil | 代码中出现的全局变量(带有名称、行和列),如果编译器选项 `lint_global` 为 false 则为 nil。 |
4702
4703#### file_exist
4704
4705**类型:** 函数。
4706
4707**描述:**
4708
4709检查源文件是否存在的函数。可以覆盖该函数以自定义行为。
4710
4711**签名:**
4712```lua
4713file_exist: function(filename: string): boolean
4714```
4715
4716**参数:**
4717
4718| 参数名 | 类型 | 描述 |
4719| --- | --- | --- |
4720| filename | string | 文件名。 |
4721
4722**返回值:**
4723
4724| 返回类型 | 描述 |
4725| --- | --- |
4726| boolean | 文件是否存在。 |
4727
4728#### read_file
4729
4730**类型:** 函数。
4731
4732**描述:**
4733
4734读取源文件的函数。可以覆盖该函数以自定义行为。
4735
4736**签名:**
4737```lua
4738read_file: function(filename: string): string
4739```
4740
4741**参数:**
4742
4743| 参数名 | 类型 | 描述 |
4744| --- | --- | --- |
4745| filename | string | 文件名。 |
4746
4747**返回值:**
4748
4749| 返回类型 | 描述 |
4750| --- | --- |
4751| string | 文件内容。 |
4752
4753#### insert_loader
4754
4755**类型:** 函数。
4756
4757**描述:**
4758
4759将 YueScript 加载器插入到 Lua 包加载器(搜索器)中。
4760
4761**签名:**
4762```lua
4763insert_loader: function(pos?: integer): boolean
4764```
4765
4766**参数:**
4767
4768| 参数名 | 类型 | 描述 |
4769| --- | --- | --- |
4770| pos | integer | [可选] 要插入加载器的位置。默认为 3。 |
4771
4772**返回值:**
4773
4774| 返回类型 | 描述 |
4775| --- | --- |
4776| boolean | 是否成功插入加载器。如果加载器已经插入,则返回失败。 |
4777
4778#### remove_loader
4779
4780**类型:** 函数。
4781
4782**描述:**
4783
4784从 Lua 包加载器(搜索器)中移除 YueScript 加载器。
4785
4786**签名:**
4787```lua
4788remove_loader: function(): boolean
4789```
4790
4791**返回值:**
4792
4793| 返回类型 | 描述 |
4794| --- | --- |
4795| boolean | 是否成功移除加载器。如果加载器未插入,则返回失败。 |
4796
4797#### loadstring
4798
4799**类型:** 函数。
4800
4801**描述:**
4802
4803将 YueScript 代码字符串加载为一个函数。
4804
4805**签名:**
4806```lua
4807loadstring: function(input: string, chunkname: string, env: table, config?: Config):
4808 --[[loaded function]] nil | function(...: any): (any...),
4809 --[[error]] string | nil
4810```
4811
4812**参数:**
4813
4814| 参数名 | 类型 | 描述 |
4815| --- | --- | --- |
4816| input | string | YueScript 代码。 |
4817| chunkname | string | 代码块的名称。 |
4818| env | table | 环境表。 |
4819| config | Config | [可选] 编译器选项。 |
4820
4821**返回值:**
4822
4823| 返回类型 | 描述 |
4824| --- | --- |
4825| function \| nil | 加载的函数,如果加载失败则为 nil。 |
4826| string \| nil | 错误消息,如果加载成功则为 nil。 |
4827
4828#### loadstring
4829
4830**类型:** 函数。
4831
4832**描述:**
4833
4834将 YueScript 代码字符串加载为一个函数。
4835
4836**签名:**
4837```lua
4838loadstring: function(input: string, chunkname: string, config?: Config):
4839 --[[loaded function]] nil | function(...: any): (any...),
4840 --[[error]] string | nil
4841```
4842
4843**参数:**
4844
4845| 参数名 | 类型 | 描述 |
4846| --- | --- | --- |
4847| input | string | YueScript 代码。 |
4848| chunkname | string | 代码块的名称。 |
4849| config | Config | [可选] 编译器选项。 |
4850
4851**返回值:**
4852
4853| 返回类型 | 描述 |
4854| --- | --- |
4855| function \| nil | 加载的函数,如果加载失败则为 nil。 |
4856| string \| nil | 错误消息,如果加载成功则为 nil。 |
4857
4858#### loadstring
4859
4860**类型:** 函数。
4861
4862**描述:**
4863
4864将 YueScript 代码字符串加载为一个函数。
4865
4866**签名:**
4867```lua
4868loadstring: function(input: string, config?: Config):
4869 --[[loaded function]] nil | function(...: any): (any...),
4870 --[[error]] string | nil
4871```
4872
4873**参数:**
4874
4875| 参数名 | 类型 | 描述 |
4876| --- | --- | --- |
4877| input | string | YueScript 代码。 |
4878| config | Config | [可选] 编译器选项。 |
4879
4880**返回值:**
4881
4882| 返回类型 | 描述 |
4883| --- | --- |
4884| function \| nil | 加载的函数,如果加载失败则为 nil。 |
4885| string \| nil | 错误消息,如果加载成功则为 nil。 |
4886
4887#### loadfile
4888
4889**类型:** 函数。
4890
4891**描述:**
4892
4893将 YueScript 代码文件加载为一个函数。
4894
4895**签名:**
4896```lua
4897loadfile: function(filename: string, env: table, config?: Config):
4898 nil | function(...: any): (any...),
4899 string | nil
4900```
4901
4902**参数:**
4903
4904| 参数名 | 类型 | 描述 |
4905| --- | --- | --- |
4906| filename | string | 文件名。 |
4907| env | table | 环境表。 |
4908| config | Config | [可选] 编译器选项。 |
4909
4910**返回值:**
4911
4912| 返回类型 | 描述 |
4913| --- | --- |
4914| function \| nil | 加载的函数,如果加载失败则为 nil。 |
4915| string \| nil | 错误消息,如果加载成功则为 nil。 |
4916
4917#### loadfile
4918
4919**类型:** 函数。
4920
4921**描述:**
4922
4923将 YueScript 代码文件加载为一个函数。
4924
4925**签名:**
4926```lua
4927loadfile: function(filename: string, config?: Config):
4928 nil | function(...: any): (any...),
4929 string | nil
4930```
4931
4932**参数:**
4933
4934| 参数名 | 类型 | 描述 |
4935| --- | --- | --- |
4936| filename | string | 文件名。 |
4937| config | Config | [可选] 编译器选项。 |
4938
4939**返回值:**
4940
4941| 返回类型 | 描述 |
4942| --- | --- |
4943| function \| nil | 加载的函数,如果加载失败则为 nil。 |
4944| string \| nil | 错误消息,如果加载成功则为 nil。 |
4945
4946#### dofile
4947
4948**类型:** 函数。
4949
4950**描述:**
4951
4952将 YueScript 代码文件加载为一个函数并执行。
4953
4954**签名:**
4955```lua
4956dofile: function(filename: string, env: table, config?: Config): any...
4957```
4958
4959**参数:**
4960
4961| 参数名 | 类型 | 描述 |
4962| --- | --- | --- |
4963| filename | string | 文件名。 |
4964| env | table | 环境表。 |
4965| config | Config | [可选] 编译器选项。 |
4966
4967**返回值:**
4968
4969| 返回类型 | 描述 |
4970| --- | --- |
4971| any... | 加载的函数执行后的返回值。 |
4972
4973#### dofile
4974
4975**类型:** 函数。
4976
4977**描述:**
4978
4979将 YueScript 代码文件加载为一个函数并执行。
4980
4981**签名:**
4982```lua
4983dofile: function(filename: string, config?: Config): any...
4984```
4985
4986**参数:**
4987
4988| 参数名 | 类型 | 描述 |
4989| --- | --- | --- |
4990| filename | string | 文件名。 |
4991| config | Config | [可选] 编译器选项。 |
4992
4993**返回值:**
4994
4995| 返回类型 | 描述 |
4996| --- | --- |
4997| any... | 加载的函数执行后的返回值。 |
4998
4999#### find_modulepath
5000
5001**类型:** 函数。
5002
5003**描述:**
5004
5005将 YueScript 模块名解析为文件路径。
5006
5007**签名:**
5008```lua
5009find_modulepath: function(name: string): string
5010```
5011
5012**参数:**
5013
5014| 参数名 | 类型 | 描述 |
5015| --- | --- | --- |
5016| name | string | 模块名。 |
5017
5018**返回值:**
5019
5020| 返回类型 | 描述 |
5021| --- | --- |
5022| string | 文件路径。 |
5023
5024#### pcall
5025
5026**类型:** 函数。
5027
5028**描述:**
5029
5030在保护模式下调用一个函数。
5031会捕获任何错误,执行成功则返回成功状态和结果,否则为失败状态和错误信息。
5032当发生错误时,将错误信息中的代码行号重写为 YueScript 代码中的原始行号。
5033
5034**签名:**
5035```lua
5036pcall: function(f: function, ...: any): boolean, any...
5037```
5038
5039**参数:**
5040
5041| 参数名 | 类型 | 描述 |
5042| --- | --- | --- |
5043| f | function | 要调用的函数。 |
5044| ... | any | 要传递给函数的参数。 |
5045
5046**返回值:**
5047
5048| 返回类型 | 描述 |
5049| --- | --- |
5050| boolean, ... | 状态码和函数结果或错误信息。 |
5051
5052#### require
5053
5054**类型:** 函数。
5055
5056**描述:**
5057
5058加载给定的模块。可以是 Lua 模块或 YueScript 模块。
5059如果模块是 YueScript 模块且加载失败,则将错误信息中的代码行号重写为 YueScript 代码中的原始行号。
5060
5061**签名:**
5062```lua
5063require: function(name: string): any...
5064```
5065
5066**参数:**
5067
5068| 参数名 | 类型 | 描述 |
5069| --- | --- | --- |
5070| modname | string | 要加载的模块名。 |
5071
5072**返回值:**
5073
5074| 返回类型 | 描述 |
5075| --- | --- |
5076| any | 如果模块已经加载,则返回 package.loaded[modname] 中存储的值。否则,尝试查找加载器并返回 package.loaded[modname] 的最终值和加载器数据作为第二个结果。 |
5077
5078#### p
5079
5080**类型:** 函数。
5081
5082**描述:**
5083
5084检查传递的值的内部结构,并打印值出它的字符串表示。
5085
5086**签名:**
5087```lua
5088p: function(...: any)
5089```
5090
5091**参数:**
5092
5093| 参数名 | 类型 | 描述 |
5094| --- | --- | --- |
5095| ... | any | 要检查的值。 |
5096
5097#### options
5098
5099**类型:** 成员变量。
5100
5101**描述:**
5102
5103当前编译器选项。
5104
5105**签名:**
5106```lua
5107options: Config.Options
5108```
5109
5110#### traceback
5111
5112**类型:** 函数。
5113
5114**描述:**
5115
5116重写堆栈跟踪中的行号为 YueScript 代码中的原始行号的 traceback 函数。
5117
5118**签名:**
5119```lua
5120traceback: function(message: string): string
5121```
5122
5123**参数:**
5124
5125| 参数名 | 类型 | 描述 |
5126| --- | --- | --- |
5127| message | string | 堆栈跟踪消息。 |
5128
5129**返回值:**
5130
5131| 返回类型 | 描述 |
5132| --- | --- |
5133| string | 重写后的堆栈跟踪消息。 |
5134
5135#### is_ast
5136
5137**类型:** 函数。
5138
5139**描述:**
5140
5141检查代码是否匹配指定的 AST。
5142
5143**签名:**
5144```lua
5145is_ast: function(astName: string, code: string): boolean
5146```
5147
5148**参数:**
5149
5150| 参数名 | 类型 | 描述 |
5151| --- | --- | --- |
5152| astName | string | AST 名称。 |
5153| code | string | 代码。 |
5154
5155**返回值:**
5156
5157| 返回类型 | 描述 |
5158| --- | --- |
5159| boolean | 代码是否匹配 AST。 |
5160
5161#### AST
5162
5163**类型:** 成员变量。
5164
5165**描述:**
5166
5167AST 类型定义,带有名称、行、列和子节点。
5168
5169**签名:**
5170```lua
5171type AST = {string, integer, integer, any}
5172```
5173
5174#### to_ast
5175
5176**类型:** 函数。
5177
5178**描述:**
5179
5180将代码转换为 AST。
5181
5182**签名:**
5183```lua
5184to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean):
5185 --[[AST]] AST | nil,
5186 --[[error]] nil | string
5187```
5188
5189**参数:**
5190
5191| 参数名 | 类型 | 描述 |
5192| --- | --- | --- |
5193| code | string | 代码。 |
5194| flattenLevel | integer | [可选] 扁平化级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 |
5195| astName | string | [可选] AST 名称。默认为 "File"。 |
5196| reserveComment | boolean | [可选] 是否保留原始注释。默认为 false。 |
5197
5198**返回值:**
5199
5200| 返回类型 | 描述 |
5201| --- | --- |
5202| AST \| nil | AST,如果转换失败则为 nil。 |
5203| string \| nil | 错误消息,如果转换成功则为 nil。 |
5204
5205#### format
5206
5207**类型:** 函数。
5208
5209**描述:**
5210
5211格式化 YueScript 代码。
5212
5213**签名:**
5214```lua
5215format: function(code: string, tabSize?: number, reserveComment?: boolean): string
5216```
5217
5218**参数:**
5219
5220| 参数名 | 类型 | 描述 |
5221| --- | --- | --- |
5222| code | string | 代码。 |
5223| tabSize | integer | [可选] 制表符大小。默认为 4。 |
5224| reserveComment | boolean | [可选] 是否保留原始注释。默认为 true。 |
5225
5226**返回值:**
5227
5228| 返回类型 | 描述 |
5229| --- | --- |
5230| string | 格式化后的代码。 |
5231
5232#### __call
5233
5234**类型:** 元方法。
5235
5236**描述:**
5237
5238导入 YueScript 模块。
5239如果发生加载失败,则将错误信息中的代码行号重写为 YueScript 代码中的原始行号。
5240
5241**签名:**
5242```lua
5243metamethod __call: function(self: yue, module: string): any...
5244```
5245
5246**参数:**
5247
5248| 参数名 | 类型 | 描述 |
5249| --- | --- | --- |
5250| module | string | 模块名。 |
5251
5252**返回值:**
5253
5254| 返回类型 | 描述 |
5255| --- | --- |
5256| any | 模块值。 |
5257
5258### Config
5259
5260**描述:**
5261
5262编译器编译选项。
5263
5264#### lint_global
5265
5266**类型:** 成员变量。
5267
5268**描述:**
5269
5270编译器是否应该收集代码中出现的全局变量。
5271
5272**签名:**
5273```lua
5274lint_global: boolean
5275```
5276
5277#### implicit_return_root
5278
5279**类型:** 成员变量。
5280
5281**描述:**
5282
5283编译器是否应该对根层级的代码块进行隐式的表达式返回。
5284
5285**签名:**
5286```lua
5287implicit_return_root: boolean
5288```
5289
5290#### reserve_line_number
5291
5292**类型:** 成员变量。
5293
5294**描述:**
5295
5296编译器是否应该在编译后的代码中保留原始行号。
5297
5298**签名:**
5299```lua
5300reserve_line_number: boolean
5301```
5302
5303#### reserve_comment
5304
5305**类型:** 成员变量。
5306
5307**描述:**
5308
5309编译器是否应该在编译后的代码中保留原始注释。
5310
5311**签名:**
5312```lua
5313reserve_comment: boolean
5314```
5315
5316#### space_over_tab
5317
5318**类型:** 成员变量。
5319
5320**描述:**
5321
5322编译器是否应该在编译后的代码中使用空格字符而不是制表符字符。
5323
5324**签名:**
5325```lua
5326space_over_tab: boolean
5327```
5328
5329#### same_module
5330
5331**类型:** 成员变量。
5332
5333**描述:**
5334
5335编译器是否应该将要编译的代码视为当前正在编译的模块。仅供编译器内部使用。
5336
5337**签名:**
5338```lua
5339same_module: boolean
5340```
5341
5342#### line_offset
5343
5344**类型:** 成员变量。
5345
5346**描述:**
5347
5348编译器错误消息是否应该包含行号偏移量。仅供编译器内部使用。
5349
5350**签名:**
5351```lua
5352line_offset: integer
5353```
5354
5355#### yue.Config.LuaTarget
5356
5357**类型:** 枚举。
5358
5359**描述:**
5360
5361目标 Lua 版本枚举。
5362
5363**签名:**
5364```lua
5365enum LuaTarget
5366 "5.1"
5367 "5.2"
5368 "5.3"
5369 "5.4"
5370 "5.5"
5371end
5372```
5373
5374#### options
5375
5376**类型:** 成员变量。
5377
5378**描述:**
5379
5380要传递给编译函数的额外选项。
5381
5382**签名:**
5383```lua
5384options: Options
5385```
5386
5387### Options
5388
5389**描述:**
5390
5391额外编译器选项定义。
5392
5393#### target
5394
5395**类型:** 成员变量。
5396
5397**描述:**
5398
5399编译目标 Lua 版本。
5400
5401**签名:**
5402```lua
5403target: LuaTarget
5404```
5405
5406#### path
5407
5408**类型:** 成员变量。
5409
5410**描述:**
5411
5412额外模块搜索路径。
5413
5414**签名:**
5415```lua
5416path: string
5417```
5418
5419#### dump_locals
5420
5421**类型:** 成员变量。
5422
5423**描述:**
5424
5425是否在回溯错误消息中输出代码块的局部变量。默认为 false。
5426
5427**签名:**
5428```lua
5429dump_locals: boolean
5430```
5431
5432#### simplified
5433
5434**类型:** 成员变量。
5435
5436**描述:**
5437
5438是否简化输出的错误消息。默认为 true。
5439
5440**签名:**
5441```lua
5442simplified: boolean
5443```
5444
5445## MIT 许可证
5446
5447版权 (c) 2017-2025 李瑾 \<dragon-fly@qq.com\>
5448
5449特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下:
5450上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
5451本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
5452
5453<CompilerModal />
diff --git a/doc/docs/zh/doc/installation.md b/doc/docs/zh/doc/installation.md
new file mode 100644
index 0000000..618da2a
--- /dev/null
+++ b/doc/docs/zh/doc/installation.md
@@ -0,0 +1,43 @@
1# 安装
2
3## Lua 模块
4
5&emsp;安装 [luarocks](https://luarocks.org),一个 Lua 模块的包管理器。然后作为 Lua 模块和可执行文件安装它:
6
7```shell
8luarocks install yuescript
9```
10
11&emsp;或者你可以自己构建 `yue.so` 文件:
12
13```shell
14make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua
15```
16
17&emsp;然后从路径 **bin/shared/yue.so** 获取二进制文件。
18
19## 构建二进制工具
20
21&emsp;克隆项目仓库,然后构建并安装可执行文件:
22
23```shell
24make install
25```
26
27&emsp;构建不带宏功能的月之脚本编译工具:
28
29```shell
30make install NO_MACRO=true
31```
32
33&emsp;构建不带内置Lua二进制文件的月之脚本编译工具:
34
35```shell
36make install NO_LUA=true
37```
38
39## 下载预编译的二进制程序
40
41&emsp;你可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。
42
43&emsp;在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。
diff --git a/doc/docs/zh/doc/introduction.md b/doc/docs/zh/doc/introduction.md
new file mode 100644
index 0000000..827d163
--- /dev/null
+++ b/doc/docs/zh/doc/introduction.md
@@ -0,0 +1,103 @@
1# 介绍
2
3月之脚本(YueScript)是一种动态语言,可以编译为 Lua。它是 [MoonScript](https://github.com/leafo/moonscript) 的方言。用月之脚本编写的代码既有表现力又非常简洁。它适合编写一些更易于维护的代码,并在嵌入 Lua 的环境中运行,如游戏或网站服务器。
4
5Yue(月)是中文中“月亮”的名称。
6
7## 月之脚本概览
8```yuescript
9-- 导入语法
10import p, to_lua from "yue"
11
12-- 隐式对象
13inventory =
14 equipment:
15 - "sword"
16 - "shield"
17 items:
18 - name: "potion"
19 count: 10
20 - name: "bread"
21 count: 3
22
23-- 列表推导
24map = (arr, action) ->
25 [action item for item in *arr]
26
27filter = (arr, cond) ->
28 [item for item in *arr when cond item]
29
30reduce = (arr, init, action): init ->
31 init = action init, item for item in *arr
32
33-- 管道操作符
34[1, 2, 3]
35 |> map (x) -> x * 2
36 |> filter (x) -> x > 4
37 |> reduce 0, (a, b) -> a + b
38 |> print
39
40-- 元表操作
41apple =
42 size: 15
43 <index>:
44 color: 0x00ffff
45
46with apple
47 p .size, .color, .<index> if .<>?
48
49-- 类似js的导出语法
50export 🌛 = "月之脚本"
51```
52<YueDisplay>
53
54```yue
55-- 导入语法
56import p, to_lua from "yue"
57
58-- 隐式对象
59inventory =
60 equipment:
61 - "sword"
62 - "shield"
63 items:
64 - name: "potion"
65 count: 10
66 - name: "bread"
67 count: 3
68
69-- 列表推导
70map = (arr, action) ->
71 [action item for item in *arr]
72
73filter = (arr, cond) ->
74 [item for item in *arr when cond item]
75
76reduce = (arr, init, action): init ->
77 init = action init, item for item in *arr
78
79-- 管道操作符
80[1, 2, 3]
81 |> map (x) -> x * 2
82 |> filter (x) -> x > 4
83 |> reduce 0, (a, b) -> a + b
84 |> print
85
86-- 元表操作
87apple =
88 size: 15
89 <index>:
90 color: 0x00ffff
91
92with apple
93 p .size, .color, .<index> if .<>?
94
95-- 类似js的导出语法
96export 🌛 = "月之脚本"
97```
98
99</YueDisplay>
100
101## 关于 Dora SSR
102
103月之脚本是与开源游戏引擎 [Dora SSR](https://github.com/Dora-SSR/Dora-SSR) 一起开发和维护的。它已被用于创建引擎工具、游戏原型和演示,在实际的游戏项目中验证其能力,同时它也帮助增强了 Dora SSR 游戏引擎的开发体验。
diff --git a/doc/docs/zh/doc/licence-mit.md b/doc/docs/zh/doc/licence-mit.md
new file mode 100644
index 0000000..1a07518
--- /dev/null
+++ b/doc/docs/zh/doc/licence-mit.md
@@ -0,0 +1,9 @@
1# MIT 许可证
2
3版权 (c) 2017-2026 李瑾 \<dragon-fly@qq.com\>
4
5特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下:
6上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
7本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
8
9<CompilerModal />
diff --git a/doc/docs/zh/doc/line-decorators.md b/doc/docs/zh/doc/line-decorators.md
new file mode 100644
index 0000000..86a1bd9
--- /dev/null
+++ b/doc/docs/zh/doc/line-decorators.md
@@ -0,0 +1,44 @@
1# 代码行修饰
2
3&emsp;&emsp;为了方便编写代码,循环语句和 if 语句可以应用于单行代码语句的末尾:
4
5```yuescript
6print "你好,世界" if name == "Rob"
7```
8<YueDisplay>
9
10```yue
11print "你好,世界" if name == "Rob"
12```
13
14</YueDisplay>
15
16&emsp;&emsp;修饰 for 循环的示例:
17
18```yuescript
19print "项目: ", item for item in *items
20```
21<YueDisplay>
22
23```yue
24print "项目: ", item for item in *items
25```
26
27</YueDisplay>
28
29&emsp;&emsp;修饰 while 循环的示例:
30
31```yuescript
32game\update! while game\isRunning!
33
34reader\parse_line! until reader\eof!
35```
36<YueDisplay>
37
38```yue
39game\update! while game\isRunning!
40
41reader\parse_line! until reader\eof!
42```
43
44</YueDisplay>
diff --git a/doc/docs/zh/doc/literals.md b/doc/docs/zh/doc/literals.md
new file mode 100644
index 0000000..1592bae
--- /dev/null
+++ b/doc/docs/zh/doc/literals.md
@@ -0,0 +1,111 @@
1# 字面量
2
3&emsp;&emsp;Lua 中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和 **nil**。
4
5&emsp;&emsp;但与 Lua 不同的是,单引号和双引号字符串内部允许有换行:
6
7```yuescript
8some_string = "这是一个字符串
9 并包括一个换行。"
10
11-- 使用#{}语法可以将表达式插入到字符串字面量中。
12-- 字符串插值只在双引号字符串中可用。
13print "我有#{math.random! * 100}%的把握。"
14```
15<YueDisplay>
16
17```yue
18some_string = "这是一个字符串
19 并包括一个换行。"
20
21-- 使用#{}语法可以将表达式插入到字符串字面量中。
22-- 字符串插值只在双引号字符串中可用。
23print "我有#{math.random! * 100}%的把握。"
24```
25
26</YueDisplay>
27
28## 数字字面量
29
30&emsp;&emsp;你可以在数字字面量中使用下划线来增加可读性。
31
32```yuescript
33integer = 1_000_000
34hex = 0xEF_BB_BF
35binary = 0B10011
36```
37<YueDisplay>
38
39
40```yue
41integer = 1_000_000
42hex = 0xEF_BB_BF
43binary = 0B10011
44```
45
46</YueDisplay>
47
48## YAML 风格字符串
49
50&emsp;&emsp;使用 `|` 前缀标记一个多行 YAML 风格字符串:
51
52```yuescript
53str = |
54 key: value
55 list:
56 - item1
57 - #{expr}
58```
59<YueDisplay>
60
61```yue
62str = |
63 key: value
64 list:
65 - item1
66 - #{expr}
67```
68
69</YueDisplay>
70
71&emsp;&emsp;其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。
72
73&emsp;&emsp;YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。
74
75```yuescript
76fn = ->
77 str = |
78 foo:
79 bar: baz
80 return str
81```
82<YueDisplay>
83
84```yue
85fn = ->
86 str = |
87 foo:
88 bar: baz
89 return str
90```
91
92</YueDisplay>
93
94&emsp;&emsp;输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。
95
96&emsp;&emsp;支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义:
97
98```yuescript
99str = |
100 path: "C:\Program Files\App"
101 note: 'He said: "#{Hello}!"'
102```
103<YueDisplay>
104
105```yue
106str = |
107 path: "C:\Program Files\App"
108 note: 'He said: "#{Hello}!"'
109```
110
111</YueDisplay>
diff --git a/doc/docs/zh/doc/macro.md b/doc/docs/zh/doc/macro.md
new file mode 100644
index 0000000..924b3ab
--- /dev/null
+++ b/doc/docs/zh/doc/macro.md
@@ -0,0 +1,276 @@
1# 宏
2
3## 常见用法
4
5&emsp;&emsp;宏函数用于在编译时执行一段代码来生成新的代码,并将生成的代码插入到最终编译结果中。
6
7```yuescript
8macro PI2 = -> math.pi * 2
9area = $PI2 * 5
10
11macro HELLO = -> "'你好 世界'"
12print $HELLO
13
14macro config = (debugging) ->
15 global debugMode = debugging == "true"
16 ""
17
18macro asserts = (cond) ->
19 debugMode and "assert #{cond}" or ""
20
21macro assert = (cond) ->
22 debugMode and "assert #{cond}" or "#{cond}"
23
24$config true
25$asserts item ~= nil
26
27$config false
28value = $assert item
29
30-- 宏函数参数传递的表达式会被转换为字符串
31macro and = (...) -> "#{ table.concat {...}, ' and ' }"
32if $and f1!, f2!, f3!
33 print "OK"
34```
35<YueDisplay>
36
37```yue
38macro PI2 = -> math.pi * 2
39area = $PI2 * 5
40
41macro HELLO = -> "'你好 世界'"
42print $HELLO
43
44macro config = (debugging) ->
45 global debugMode = debugging == "true"
46 ""
47
48macro asserts = (cond) ->
49 debugMode and "assert #{cond}" or ""
50
51macro assert = (cond) ->
52 debugMode and "assert #{cond}" or "#{cond}"
53
54$config true
55$asserts item ~= nil
56
57$config false
58value = $assert item
59
60-- 宏函数参数传递的表达式会被转换为字符串
61macro and = (...) -> "#{ table.concat {...}, ' and ' }"
62if $and f1!, f2!, f3!
63 print "OK"
64```
65
66</YueDisplay>
67
68## 直接插入代码
69
70&emsp;&emsp;宏函数可以返回一个包含月之脚本代码的字符串,或是一个包含 Lua 代码字符串的配置表。
71
72```yuescript
73macro yueFunc = (var) -> "local #{var} = ->"
74$yueFunc funcA
75funcA = -> "无法访问宏生成月之脚本里定义的变量"
76
77macro luaFunc = (var) -> {
78 code: "local function #{var}() end"
79 type: "lua"
80}
81$luaFunc funcB
82funcB = -> "无法访问宏生成 Lua 代码里定义的变量"
83
84macro lua = (code) -> {
85 :code
86 type: "lua"
87}
88
89-- raw字符串的开始和结束符号会自动被去除了再传入宏函数
90$lua[==[
91-- 插入原始Lua代码
92if cond then
93 print("输出")
94end
95]==]
96```
97<YueDisplay>
98
99```yue
100macro yueFunc = (var) -> "local #{var} = ->"
101$yueFunc funcA
102funcA = -> "无法访问宏生成月之脚本里定义的变量"
103
104macro luaFunc = (var) -> {
105 code: "local function #{var}() end"
106 type: "lua"
107}
108$luaFunc funcB
109funcB = -> "无法访问宏生成 Lua 代码里定义的变量"
110
111macro lua = (code) -> {
112 :code
113 type: "lua"
114}
115
116-- raw字符串的开始和结束符号会自动被去除了再传入宏函数
117$lua[==[
118-- 插入原始Lua代码
119if cond then
120 print("输出")
121end
122]==]
123```
124
125</YueDisplay>
126
127## 导出宏
128
129&emsp;&emsp;宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。
130
131```yuescript
132-- 文件: utils.yue
133export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
134export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
135export macro foreach = (items, action) -> "for _ in *#{items}
136 #{action}"
137
138-- 文件 main.yue
139import "utils" as {
140 $, -- 表示导入所有宏的符号
141 $foreach: $each -- 重命名宏 $foreach 为 $each
142}
143[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
144```
145<YueDisplay>
146
147```yue
148-- 文件: utils.yue
149export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
150export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
151export macro foreach = (items, action) -> "for _ in *#{items}
152 #{action}"
153-- 文件 main.yue
154-- 在浏览器中不支持import函数,请在真实环境中尝试
155--[[
156import "utils" as {
157 $, -- 表示导入所有宏的符号
158 $foreach: $each -- 重命名宏 $foreach 为 $each
159}
160[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
161]]
162```
163
164</YueDisplay>
165
166## 内置宏
167
168&emsp;&emsp;月之脚本中有一些内置可以直接使用的宏,但你可以通过声明相同名称的宏来覆盖它们。
169
170```yuescript
171print $FILE -- 获取当前模块名称的字符串
172print $LINE -- 获取当前代码行数:2
173```
174<YueDisplay>
175
176```yue
177print $FILE -- 获取当前模块名称的字符串
178print $LINE -- 获取当前代码行数:2
179```
180
181</YueDisplay>
182
183## 用宏生成宏
184
185&emsp;&emsp;在月之脚本中,宏函数允许你在编译时生成代码。通过嵌套的宏函数,你可以创建更复杂的生成模式。这个特性允许你定义一个宏函数,用它来生成另一个宏函数,从而实现更加动态的代码生成。
186
187```yuescript
188macro Enum = (...) ->
189 items = {...}
190 itemSet = {item, true for item in *items}
191 (item) ->
192 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
193 "\"#{item}\""
194
195macro BodyType = $Enum(
196 Static
197 Dynamic
198 Kinematic
199)
200
201print "有效的枚举类型:", $BodyType Static
202-- print "编译报错的枚举类型:", $BodyType Unknown
203```
204<YueDisplay>
205
206```yue
207macro Enum = (...) ->
208 items = {...}
209 itemSet = {item, true for item in *items}
210 (item) ->
211 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
212 "\"#{item}\""
213
214macro BodyType = $Enum(
215 Static
216 Dynamic
217 Kinematic
218)
219
220print "有效的枚举类型:", $BodyType Static
221-- print "编译报错的枚举类型:", $BodyType Unknown
222```
223
224</YueDisplay>
225
226## 宏参数检查
227
228&emsp;&emsp;可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。
229
230```yuescript
231macro printNumAndStr = (num `Num, str `String) -> |
232 print(
233 #{num}
234 #{str}
235 )
236
237$printNumAndStr 123, "hello"
238```
239<YueDisplay>
240
241```yue
242macro printNumAndStr = (num `Num, str `String) -> |
243 print(
244 #{num}
245 #{str}
246 )
247
248$printNumAndStr 123, "hello"
249```
250
251</YueDisplay>
252
253&emsp;&emsp;如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。
254
255```yuescript
256macro printNumAndStr = (num, str) ->
257 error "expected Num as first argument" unless $is_ast Num, num
258 error "expected String as second argument" unless $is_ast String, str
259 "print(#{num}, #{str})"
260
261$printNumAndStr 123, "hello"
262```
263<YueDisplay>
264
265```yue
266macro printNumAndStr = (num, str) ->
267 error "expected Num as first argument" unless $is_ast Num, num
268 error "expected String as second argument" unless $is_ast String, str
269 "print(#{num}, #{str})"
270
271$printNumAndStr 123, "hello"
272```
273
274</YueDisplay>
275
276&emsp;&emsp;更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。
diff --git a/doc/docs/zh/doc/module.md b/doc/docs/zh/doc/module.md
new file mode 100644
index 0000000..bae6618
--- /dev/null
+++ b/doc/docs/zh/doc/module.md
@@ -0,0 +1,245 @@
1# 模块
2
3## 导入
4
5&emsp;&emsp;导入语句是一个语法糖,用于需要引入一个模块或者从已导入的模块中提取子项目。从模块导入的变量默认为不可修改的常量。
6
7```yuescript
8-- 用作表解构
9do
10 import insert, concat from table
11 -- 当给 insert, concat 变量赋值时,编译器会报告错误
12 import C, Ct, Cmt from require "lpeg"
13 -- 快捷写法引入模块的子项
14 import x, y, z from 'mymodule'
15 -- 使用Python风格的导入
16 from 'module' import a, b, c
17
18-- 快捷地导入一个模块
19do
20 import 'module'
21 import 'module_x'
22 import "d-a-s-h-e-s"
23 import "module.part"
24
25-- 导入模块后起一个别名使用,或是进行导入模块表的解构
26do
27 import "player" as PlayerModule
28 import "lpeg" as :C, :Ct, :Cmt
29 import "export" as {one, two, Something:{umm:{ch}}}
30```
31<YueDisplay>
32
33```yue
34-- 用作表解构
35do
36 import insert, concat from table
37 -- 当给 insert, concat 变量赋值时,编译器会报告错误
38 import C, Ct, Cmt from require "lpeg"
39 -- 快捷写法引入模块的子项
40 import x, y, z from 'mymodule'
41 -- 使用Python风格的导入
42 from 'module' import a, b, c
43
44-- 快捷地导入一个模块
45do
46 import 'module'
47 import 'module_x'
48 import "d-a-s-h-e-s"
49 import "module.part"
50
51-- 导入模块后起一个别名使用,或是进行导入模块表的解构
52do
53 import "player" as PlayerModule
54 import "lpeg" as :C, :Ct, :Cmt
55 import "export" as {one, two, Something:{umm:{ch}}}
56```
57
58</YueDisplay>
59
60## 导入全局变量
61
62&emsp;&emsp;你可以使用 `import` 将指定的全局变量导入到本地变量中。当导入一系列对全局变量的链式访问时,最后一个访问的字段将被赋值给本地变量。
63
64```yuescript
65do
66 import tostring
67 import table.concat
68 print concat ["a", tostring 1]
69```
70<YueDisplay>
71
72```yue
73do
74 import tostring
75 import table.concat
76 print concat ["a", tostring 1]
77```
78
79</YueDisplay>
80
81### 自动全局变量导入
82
83&emsp;&emsp;在一个代码块的顶部写 `import global`,会将当前作用域中尚未显式声明或赋值过的变量名,自动导入为本地常量,并在该语句的位置绑定到同名的全局变量。
84
85&emsp;&emsp;但是在同一作用域中被显式声明为全局的变量不会被自动导入,因此可以继续进行赋值操作。
86
87```yuescript
88do
89 import global
90 print "hello"
91 math.random 3
92 -- print = nil -- 报错:自动导入的全局变量为常量
93
94do
95 -- 被显式声明为全局的变量不会被自动导入
96 import global
97 global FLAG
98 print FLAG
99 FLAG = 123
100```
101<YueDisplay>
102
103```yue
104do
105 import global
106 print "hello"
107 math.random 3
108 -- print = nil -- 报错:自动导入的全局变量是常量
109
110do
111 -- 被显式声明为全局的变量不会被自动导入
112 import global
113 global FLAG
114 print FLAG
115 FLAG = 123
116```
117
118</YueDisplay>
119
120## 导出
121
122&emsp;&emsp;导出语句提供了一种简洁的方式来定义当前的模块。
123
124### 命名导出
125
126&emsp;&emsp;带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。
127
128```yuescript
129export a, b, c = 1, 2, 3
130export cool = "cat"
131
132export What = if this
133 "abc"
134else
135 "def"
136
137export y = ->
138 hallo = 3434
139
140export class Something
141 umm: "cool"
142```
143<YueDisplay>
144
145```yue
146export a, b, c = 1, 2, 3
147export cool = "cat"
148
149export What = if this
150 "abc"
151else
152 "def"
153
154export y = ->
155 hallo = 3434
156
157export class Something
158 umm: "cool"
159```
160
161</YueDisplay>
162
163&emsp;&emsp;使用解构进行命名导出。
164
165```yuescript
166export :loadstring, to_lua: tolua = yue
167export {itemA: {:fieldA = '默认值'}} = tb
168```
169<YueDisplay>
170
171```yue
172export :loadstring, to_lua: tolua = yue
173export {itemA: {:fieldA = '默认值'}} = tb
174```
175
176</YueDisplay>
177
178&emsp;&emsp;从模块导出命名项目时,可以不用创建局部变量。
179
180```yuescript
181export.itemA = tb
182export.<index> = items
183export["a-b-c"] = 123
184```
185<YueDisplay>
186
187```yue
188export.itemA = tb
189export.<index> = items
190export["a-b-c"] = 123
191```
192
193</YueDisplay>
194
195### 未命名导出
196
197&emsp;&emsp;未命名导出会将要导出的目标项目添加到导出表的数组部分。
198
199```yuescript
200d, e, f = 3, 2, 1
201export d, e, f
202
203export if this
204 123
205else
206 456
207
208export with tmp
209 j = 2000
210```
211<YueDisplay>
212
213```yue
214d, e, f = 3, 2, 1
215export d, e, f
216
217export if this
218 123
219else
220 456
221
222export with tmp
223 j = 2000
224```
225
226</YueDisplay>
227
228### 默认导出
229
230&emsp;&emsp;在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。
231
232```yuescript
233export default ->
234 print "你好"
235 123
236```
237<YueDisplay>
238
239```yue
240export default ->
241 print "你好"
242 123
243```
244
245</YueDisplay>
diff --git a/doc/docs/zh/doc/object-oriented-programming.md b/doc/docs/zh/doc/object-oriented-programming.md
new file mode 100644
index 0000000..9eb94d8
--- /dev/null
+++ b/doc/docs/zh/doc/object-oriented-programming.md
@@ -0,0 +1,550 @@
1# 面向对象编程
2
3&emsp;&emsp;在以下的示例中,月之脚本生成的 Lua 代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果你想知道关于面向对象功能的实现细节,再查看 Lua 代码。
4
5&emsp;&emsp;一个简单的类:
6
7```yuescript
8class Inventory
9 new: =>
10 @items = {}
11
12 add_item: (name) =>
13 if @items[name]
14 @items[name] += 1
15 else
16 @items[name] = 1
17```
18<YueDisplay>
19
20```yue
21class Inventory
22 new: =>
23 @items = {}
24
25 add_item: (name) =>
26 if @items[name]
27 @items[name] += 1
28 else
29 @items[name] = 1
30```
31
32</YueDisplay>
33
34&emsp;&emsp;在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合 Lua 表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为 “new” 的成员扮演了一个重要的角色,是作为构造函数来使用。
35
36&emsp;&emsp;值得注意的是,类中的方法都采用了粗箭头函数语法。当在类的实例上调用方法时,该实例会自动作为第一个参数被传入,因此粗箭头函数用于生成一个名为 “self” 的参数。
37
38&emsp;&emsp;此外,“@” 前缀在变量名上起到了简化作用,代表 “self”。例如,`@items` 就等同于 `self.items`。
39
40&emsp;&emsp;为了创建类的一个新实例,可以将类名当作一个函数来调用,这样就可以生成并返回一个新的实例。
41
42```yuescript
43inv = Inventory!
44inv\add_item "t-shirt"
45inv\add_item "pants"
46```
47<YueDisplay>
48
49
50```yue
51inv = Inventory!
52inv\add_item "t-shirt"
53inv\add_item "pants"
54```
55
56</YueDisplay>
57
58&emsp;&emsp;在月之脚本的类中,由于需要将类的实例作为参数传入到调用的方法中,因此使用了 **\\** 操作符做类的成员函数调用。
59
60&emsp;&emsp;需要特别注意的是,类的所有属性在其实例之间是共享的。这对于函数类型的成员属性通常不会造成问题,但对于其他类型的属性,可能会导致意外的结果。
61
62&emsp;&emsp;例如,在下面的示例中,clothes 属性在所有实例之间共享。因此,对这个属性在一个实例中的修改,将会影响到其他所有实例。
63
64```yuescript
65class Person
66 clothes: []
67 give_item: (name) =>
68 table.insert @clothes, name
69
70a = Person!
71b = Person!
72
73a\give_item "pants"
74b\give_item "shirt"
75
76-- 会同时打印出裤子和衬衫
77print item for item in *a.clothes
78```
79<YueDisplay>
80
81```yue
82class Person
83 clothes: []
84 give_item: (name) =>
85 table.insert @clothes, name
86
87a = Person!
88b = Person!
89
90a\give_item "pants"
91b\give_item "shirt"
92
93-- 会同时打印出裤子和衬衫
94print item for item in *a.clothes
95```
96
97</YueDisplay>
98
99&emsp;&emsp;避免这个问题的正确方法是在构造函数中创建对象的可变状态:
100
101```yuescript
102class Person
103 new: =>
104 @clothes = []
105```
106<YueDisplay>
107
108```yue
109class Person
110 new: =>
111 @clothes = []
112```
113
114</YueDisplay>
115
116## 继承
117
118&emsp;&emsp;`extends` 关键字可以在类声明中使用,以继承另一个类的属性和方法。
119
120```yuescript
121class BackPack extends Inventory
122 size: 10
123 add_item: (name) =>
124 if #@items > size then error "背包已满"
125 super name
126```
127<YueDisplay>
128
129```yue
130class BackPack extends Inventory
131 size: 10
132 add_item: (name) =>
133 if #@items > size then error "背包已满"
134 super name
135```
136
137</YueDisplay>
138
139&emsp;&emsp;在这一部分,我们对月之脚本中的 `Inventory` 类进行了扩展,加入了对可以携带物品数量的限制。
140
141&emsp;&emsp;在这个特定的例子中,子类并没有定义自己的构造函数。因此,当创建一个新的实例时,系统会默认调用父类的构造函数。但如果我们在子类中定义了构造函数,我们可以利用 `super` 方法来调用并执行父类的构造函数。
142
143&emsp;&emsp;此外,当一个类继承自另一个类时,它会尝试调用父类上的 `__inherited` 方法(如果这个方法存在的话),以此来向父类发送通知。这个 `__inherited` 函数接受两个参数:被继承的父类和继承的子类。
144
145```yuescript
146class Shelf
147 @__inherited: (child) =>
148 print @__name, "被", child.__name, "继承"
149
150-- 将打印: Shelf 被 Cupboard 继承
151class Cupboard extends Shelf
152```
153<YueDisplay>
154
155```yue
156class Shelf
157 @__inherited: (child) =>
158 print @__name, "被", child.__name, "继承"
159
160-- 将打印: Shelf 被 Cupboard 继承
161class Cupboard extends Shelf
162```
163
164</YueDisplay>
165
166## super 关键字
167
168&emsp;&emsp;`super` 是一个特别的关键字,它有两种不同的使用方式:既可以当作一个对象来看待,也可以像调用函数那样使用。它仅在类的内部使用时具有特殊的功能。
169
170&emsp;&emsp;当 `super` 被作为一个函数调用时,它将调用父类中与之同名的函数。此时,当前的 `self` 会自动作为第一个参数传递,正如上面提到的继承示例所展示的那样。
171
172&emsp;&emsp;在将 `super` 当作普通值使用时,它实际上是对父类对象的引用。通过这种方式,我们可以访问父类中可能被子类覆盖的值,就像访问任何普通对象一样。
173
174&emsp;&emsp;此外,当使用 `\` 操作符与 `super` 一起使用时,`self`将被插入为第一个参数,而不是使用 `super` 本身的值。而在使用`.`操作符来检索函数时,则会返回父类中的原始函数。
175
176&emsp;&emsp;下面是一些使用 `super` 的不同方法的示例:
177
178```yuescript
179class MyClass extends ParentClass
180 a_method: =>
181 -- 以下效果相同:
182 super "你好", "世界"
183 super\a_method "你好", "世界"
184 super.a_method self, "你好", "世界"
185
186 -- super 作为值等于父类:
187 assert super == ParentClass
188```
189<YueDisplay>
190
191```yue
192class MyClass extends ParentClass
193 a_method: =>
194 -- 以下效果相同:
195 super "你好", "世界"
196 super\a_method "你好", "世界"
197 super.a_method self, "你好", "世界"
198
199 -- super 作为值等于父类:
200 assert super == ParentClass
201```
202
203</YueDisplay>
204
205&emsp;&emsp;**super** 也可以用在函数存根的左侧。唯一的主要区别是,生成的函数不是绑定到 super 的值,而是绑定到 self。
206
207## 类型
208
209&emsp;&emsp;每个类的实例都带有它的类型。这存储在特殊的 \_\_class 属性中。此属性会保存类对象。类对象是我们用来构建新实例的对象。我们还可以索引类对象以检索类方法和属性。
210
211```yuescript
212b = BackPack!
213assert b.__class == BackPack
214
215print BackPack.size -- 打印 10
216```
217<YueDisplay>
218
219```yue
220b = BackPack!
221assert b.__class == BackPack
222
223print BackPack.size -- 打印 10
224```
225
226</YueDisplay>
227
228## 类对象
229
230&emsp;&emsp;在月之脚本中,当我们编写类的定义语句时,实际上是在创建一个类对象。这个类对象被保存在一个与该类同名的变量中。
231
232&emsp;&emsp;类对象具有函数的特性,可以被调用来创建新的实例。这正是我们在之前示例中所展示的创建类实例的方式。
233
234&emsp;&emsp;一个类由两个表构成:类表本身和一个基表。基表作为所有实例的元表。在类声明中列出的所有属性都存放在基表中。
235
236&emsp;&emsp;如果在类对象的元表中找不到某个属性,系统会从基表中检索该属性。这就意味着我们可以直接从类本身访问到其方法和属性。
237
238&emsp;&emsp;需要特别注意的是,对类对象的赋值并不会影响到基表,因此这不是向实例添加新方法的正确方式。相反,需要直接修改基表。关于这点,可以参考下面的 “__base” 字段。
239
240&emsp;&emsp;此外,类对象包含几个特殊的属性:当类被声明时,类的名称会作为一个字符串存储在类对象的 “__name” 字段中。
241
242```yuescript
243print BackPack.__name -- 打印 Backpack
244```
245<YueDisplay>
246
247```yue
248print BackPack.__name -- 打印 Backpack
249```
250
251</YueDisplay>
252
253&emsp;&emsp;基础对象被保存在一个名为 `__base` 的特殊表中。我们可以编辑这个表,以便为那些已经创建出来的实例和还未创建的实例增加新的功能。
254
255&emsp;&emsp;另外,如果一个类是从另一个类派生而来的,那么其父类对象则会被存储在名为 `__parent` 的地方。这种机制允许在类之间实现继承和功能扩展。
256
257## 类变量
258
259&emsp;&emsp;我们可以直接在类对象中创建变量,而不是在类的基对象中,通过在类声明中的属性名前使用 @。
260
261```yuescript
262class Things
263 @some_func: => print "Hello from", @__name
264
265Things\some_func!
266
267-- 类变量在实例中不可见
268assert Things().some_func == nil
269```
270<YueDisplay>
271
272```yue
273class Things
274 @some_func: => print "Hello from", @__name
275
276Things\some_func!
277
278-- 类变量在实例中不可见
279assert Things().some_func == nil
280```
281
282</YueDisplay>
283
284&emsp;&emsp;在表达式中,我们可以使用 @@ 来访问存储在 `self.__class` 中的值。因此,`@@hello` 是 `self.__class.hello` 的简写。
285
286```yuescript
287class Counter
288 @count: 0
289
290 new: =>
291 @@count += 1
292
293Counter!
294Counter!
295
296print Counter.count -- 输出 2
297```
298<YueDisplay>
299
300```yue
301class Counter
302 @count: 0
303
304 new: =>
305 @@count += 1
306
307Counter!
308Counter!
309
310print Counter.count -- 输出 2
311```
312
313</YueDisplay>
314
315&emsp;&emsp;@@ 的调用语义与 @ 类似。调用 @@ 时,会使用 Lua 的冒号语法将类作为第一个参数传入。
316
317```yuescript
318@@hello 1,2,3,4
319```
320<YueDisplay>
321
322```yue
323@@hello 1,2,3,4
324```
325
326</YueDisplay>
327
328## 类声明语句
329
330&emsp;&emsp;在类声明的主体中,除了键/值对外,我们还可以编写普通的表达式。在这种类声明体中的普通代码的上下文中,self 等于类对象,而不是实例对象。
331
332&emsp;&emsp;以下是创建类变量的另一种方法:
333
334```yuescript
335class Things
336 @class_var = "hello world"
337```
338<YueDisplay>
339
340```yue
341class Things
342 @class_var = "hello world"
343```
344
345</YueDisplay>
346
347&emsp;&emsp;这些表达式会在所有属性被添加到类的基对象后执行。
348
349&emsp;&emsp;在类的主体中声明的所有变量都会限制作用域只在类声明的范围。这对于放置只有类方法可以访问的私有值或辅助函数很方便:
350
351```yuescript
352class MoreThings
353 secret = 123
354 log = (msg) -> print "LOG:", msg
355
356 some_method: =>
357 log "hello world: " .. secret
358```
359<YueDisplay>
360
361```yue
362class MoreThings
363 secret = 123
364 log = (msg) -> print "LOG:", msg
365
366 some_method: =>
367 log "hello world: " .. secret
368```
369
370</YueDisplay>
371
372## @ 和 @@ 值
373
374&emsp;&emsp;当 @ 和 @@ 前缀在一个名字前时,它们分别代表在 self 和 self.\_\_class 中访问的那个名字。
375
376&emsp;&emsp;如果它们单独使用,它们是 self 和 self.\_\_class 的别名。
377
378```yuescript
379assert @ == self
380assert @@ == self.__class
381```
382<YueDisplay>
383
384```yue
385assert @ == self
386assert @@ == self.__class
387```
388
389</YueDisplay>
390
391&emsp;&emsp;例如,使用 @@ 从实例方法快速创建同一类的新实例的方法:
392
393```yuescript
394some_instance_method = (...) => @@ ...
395```
396<YueDisplay>
397
398```yue
399some_instance_method = (...) => @@ ...
400```
401
402</YueDisplay>
403
404## 构造属性提升
405
406&emsp;&emsp;为了减少编写简单值对象定义的代码。你可以这样简单写一个类:
407
408```yuescript
409class Something
410 new: (@foo, @bar, @@biz, @@baz) =>
411
412-- 这是以下声明的简写形式
413
414class Something
415 new: (foo, bar, biz, baz) =>
416 @foo = foo
417 @bar = bar
418 @@biz = biz
419 @@baz = baz
420```
421<YueDisplay>
422
423```yue
424class Something
425 new: (@foo, @bar, @@biz, @@baz) =>
426
427-- 这是以下声明的简写形式
428
429class Something
430 new: (foo, bar, biz, baz) =>
431 @foo = foo
432 @bar = bar
433 @@biz = biz
434 @@baz = baz
435```
436
437</YueDisplay>
438
439&emsp;&emsp;你也可以使用这种语法为一个函数初始化传入对象的字段。
440
441```yuescript
442new = (@fieldA, @fieldB) => @
443obj = new {}, 123, "abc"
444print obj
445```
446<YueDisplay>
447
448```yue
449new = (@fieldA, @fieldB) => @
450obj = new {}, 123, "abc"
451print obj
452```
453
454</YueDisplay>
455
456## 类表达式
457
458&emsp;&emsp;类声明的语法也可以作为一个表达式使用,可以赋值给一个变量或者被返回语句返回。
459
460```yuescript
461x = class Bucket
462 drops: 0
463 add_drop: => @drops += 1
464```
465<YueDisplay>
466
467```yue
468x = class Bucket
469 drops: 0
470 add_drop: => @drops += 1
471```
472
473</YueDisplay>
474
475## 匿名类
476
477&emsp;&emsp;声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name 属性将为 nil。如果出现在赋值语句中,赋值操作左侧的名称将代替 nil。
478
479```yuescript
480BigBucket = class extends Bucket
481 add_drop: => @drops += 10
482
483assert Bucket.__name == "BigBucket"
484```
485<YueDisplay>
486
487```yue
488BigBucket = class extends Bucket
489 add_drop: => @drops += 10
490
491assert Bucket.__name == "BigBucket"
492```
493
494</YueDisplay>
495
496&emsp;&emsp;你甚至可以省略掉主体,这意味着你可以这样写一个空白的匿名类:
497
498```yuescript
499x = class
500```
501<YueDisplay>
502
503```yue
504x = class
505```
506
507</YueDisplay>
508
509## 类混合
510
511&emsp;&emsp;你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。
512
513```yuescript
514MyIndex = __index: var: 1
515
516class X using MyIndex
517 func: =>
518 print 123
519
520x = X!
521print x.var
522
523class Y using X
524
525y = Y!
526y\func!
527
528assert y.__class.__parent ~= X -- X 不是 Y 的父类
529```
530<YueDisplay>
531
532```yue
533MyIndex = __index: var: 1
534
535class X using MyIndex
536 func: =>
537 print 123
538
539x = X!
540print x.var
541
542class Y using X
543
544y = Y!
545y\func!
546
547assert y.__class.__parent ~= X -- X 不是 Y 的父类
548```
549
550</YueDisplay>
diff --git a/doc/docs/zh/doc/operator.md b/doc/docs/zh/doc/operator.md
new file mode 100644
index 0000000..6c9fc5b
--- /dev/null
+++ b/doc/docs/zh/doc/operator.md
@@ -0,0 +1,461 @@
1# 操作符
2
3&emsp;&emsp;Lua 的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。
4
5```yuescript
6tb\func! if tb ~= nil
7tb::func! if tb != nil
8```
9<YueDisplay>
10
11```yue
12tb\func! if tb ~= nil
13tb::func! if tb != nil
14```
15
16</YueDisplay>
17
18## 链式比较
19
20&emsp;&emsp;你可以在月之脚本中进行比较表达式的链式书写:
21
22```yuescript
23print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
24-- 输出:true
25
26a = 5
27print 1 <= a <= 10
28-- 输出:true
29```
30<YueDisplay>
31
32```yue
33print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
34-- 输出:true
35
36a = 5
37print 1 <= a <= 10
38-- 输出:true
39```
40
41</YueDisplay>
42
43&emsp;&emsp;可以注意一下链式比较表达式的求值行为:
44
45```yuescript
46v = (x) ->
47 print x
48 x
49
50print v(1) < v(2) <= v(3)
51--[[
52 输出:
53 2
54 1
55 3
56 true
57]]
58
59print v(1) > v(2) <= v(3)
60--[[
61 输出:
62 2
63 1
64 false
65]]
66```
67<YueDisplay>
68
69```yue
70v = (x) ->
71 print x
72 x
73
74print v(1) < v(2) <= v(3)
75--[[
76 输出:
77 2
78 1
79 3
80 true
81]]
82
83print v(1) > v(2) <= v(3)
84--[[
85 输出:
86 2
87 1
88 false
89]]
90```
91
92</YueDisplay>
93
94&emsp;&emsp;在上面的例子里,中间的表达式 `v(2)` 仅被计算一次,如果把表达式写成 `v(1) < v(2) and v(2) <= v(3)` 的方式,中间的 `v(2)` 才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。
95
96## 表追加
97
98&emsp;&emsp;**[] =** 操作符用于向 Lua 表的最后插入值。
99
100```yuescript
101tab = []
102tab[] = "Value"
103```
104<YueDisplay>
105
106```yue
107tab = []
108tab[] = "Value"
109```
110
111</YueDisplay>
112
113&emsp;&emsp;你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中:
114
115```yuescript
116tbA = [1, 2, 3]
117tbB = [4, 5, 6]
118tbA[] = ...tbB
119-- tbA 现在为 [1, 2, 3, 4, 5, 6]
120```
121<YueDisplay>
122
123```yue
124tbA = [1, 2, 3]
125tbB = [4, 5, 6]
126tbA[] = ...tbB
127-- tbA 现在为 [1, 2, 3, 4, 5, 6]
128```
129
130</YueDisplay>
131
132## 表扩展
133
134&emsp;&emsp;你可以使用前置 `...` 操作符在 Lua 表中插入数组表或哈希表。
135
136```yuescript
137parts =
138 * "shoulders"
139 * "knees"
140lyrics =
141 * "head"
142 * ...parts
143 * "and"
144 * "toes"
145
146copy = {...other}
147
148a = {1, 2, 3, x: 1}
149b = {4, 5, y: 1}
150merge = {...a, ...b}
151```
152<YueDisplay>
153
154```yue
155parts =
156 * "shoulders"
157 * "knees"
158lyrics =
159 * "head"
160 * ...parts
161 * "and"
162 * "toes"
163
164copy = {...other}
165
166a = {1, 2, 3, x: 1}
167b = {4, 5, y: 1}
168merge = {...a, ...b}
169```
170
171</YueDisplay>
172
173## 表反向索引
174
175&emsp;&emsp;你可以使用 **#** 操作符来反向索引表中的元素。
176
177```yuescript
178last = data.items[#]
179second_last = data.items[#-1]
180data.items[#] = 1
181```
182<YueDisplay>
183
184```yue
185last = data.items[#]
186second_last = data.items[#-1]
187data.items[#] = 1
188```
189
190</YueDisplay>
191
192## 元表
193
194&emsp;&emsp;**<>** 操作符可提供元表操作的快捷方式。
195
196### 元表创建
197
198&emsp;&emsp;使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的 Lua 表。
199
200```yuescript
201mt = {}
202add = (right) => <>: mt, value: @value + right.value
203mt.__add = add
204
205a = <>: mt, value: 1
206-- 使用与临时变量名相同的字段名,将临时变量赋值给元表
207b = :<add>, value: 2
208c = <add>: mt.__add, value: 3
209
210d = a + b + c
211print d.value
212
213close _ = <close>: -> print "超出范围"
214```
215<YueDisplay>
216
217```yue
218mt = {}
219add = (right) => <>: mt, value: @value + right.value
220mt.__add = add
221
222a = <>: mt, value: 1
223-- 使用与临时变量名相同的字段名,将临时变量赋值给元表
224b = :<add>, value: 2
225c = <add>: mt.__add, value: 3
226
227d = a + b + c
228print d.value
229
230close _ = <close>: -> print "超出范围"
231```
232
233</YueDisplay>
234
235### 元表访问
236
237&emsp;&emsp;使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。
238
239```yuescript
240-- 使用包含字段 "value" 的元表创建
241tb = <"value">: 123
242tb.<index> = tb.<>
243print tb.value
244
245tb.<> = __index: {item: "hello"}
246print tb.item
247```
248<YueDisplay>
249
250
251```yue
252-- 使用包含字段 "value" 的元表创建
253tb = <"value">: 123
254tb.<index> = tb.<>
255print tb.value
256tb.<> = __index: {item: "hello"}
257print tb.item
258```
259
260</YueDisplay>
261
262### 元表解构
263
264&emsp;&emsp;使用被 **<>** 包围的元方法键解构元表。
265
266```yuescript
267{item, :new, :<close>, <index>: getter} = tb
268print item, new, close, getter
269```
270<YueDisplay>
271
272```yue
273{item, :new, :<close>, <index>: getter} = tb
274print item, new, close, getter
275```
276
277</YueDisplay>
278
279## 存在性
280
281&emsp;&emsp;**?** 运算符可以在多种上下文中用来检查存在性。
282
283```yuescript
284func?!
285print abc?["你好 世界"]?.xyz
286
287x = tab?.value
288len = utf8?.len or string?.len or (o) -> #o
289
290if print and x?
291 print x
292
293with? io.open "test.txt", "w"
294 \write "你好"
295 \close!
296```
297<YueDisplay>
298
299```yue
300func?!
301print abc?["你好 世界"]?.xyz
302
303x = tab?.value
304len = utf8?.len or string?.len or (o) -> #o
305
306if print and x?
307 print x
308
309with? io.open "test.txt", "w"
310 \write "你好"
311 \close!
312```
313
314</YueDisplay>
315
316## 管道
317
318&emsp;&emsp;与其使用一系列嵌套的函数调用,你还可以考虑使用运算符 **|>** 来传递值。
319
320```yuescript
321"你好" |> print
3221 |> print 2 -- 将管道项作为第一个参数插入
3232 |> print 1, _, 3 -- 带有占位符的管道
324
325-- 多行的管道表达式
326readFile "example.txt"
327 |> extract language, {}
328 |> parse language
329 |> emit
330 |> render
331 |> print
332```
333<YueDisplay>
334
335```yue
336"你好" |> print
3371 |> print 2 -- 将管道项作为第一个参数插入
3382 |> print 1, _, 3 -- 带有占位符的管道
339-- 多行的管道表达式
340readFile "example.txt"
341 |> extract language, {}
342 |> parse language
343 |> emit
344 |> render
345 |> print
346```
347
348</YueDisplay>
349
350## 空值合并
351
352&emsp;&emsp;如果其左操作数不是 **nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非 nil 的值,**??** 运算符将不再计算其右操作数。
353
354```yuescript
355local a, b, c, d
356a = b ?? c ?? d
357func a ?? {}
358
359a ??= false
360```
361<YueDisplay>
362
363```yue
364local a, b, c, d
365a = b ?? c ?? d
366func a ?? {}
367a ??= false
368```
369
370</YueDisplay>
371
372## 隐式对象
373
374&emsp;&emsp;你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。
375
376```yuescript
377-- 赋值时使用隐式对象
378list =
379 * 1
380 * 2
381 * 3
382
383-- 函数调用时使用隐式对象
384func
385 * 1
386 * 2
387 * 3
388
389-- 返回时使用隐式对象
390f = ->
391 return
392 * 1
393 * 2
394 * 3
395
396-- 表格时使用隐式对象
397tb =
398 name: "abc"
399
400 values:
401 - "a"
402 - "b"
403 - "c"
404
405 objects:
406 - name: "a"
407 value: 1
408 func: => @value + 1
409 tb:
410 fieldA: 1
411
412 - name: "b"
413 value: 2
414 func: => @value + 2
415 tb: { }
416```
417<YueDisplay>
418
419```yue
420-- 赋值时使用隐式对象
421list =
422 * 1
423 * 2
424 * 3
425
426-- 函数调用时使用隐式对象
427func
428 * 1
429 * 2
430 * 3
431
432-- 返回时使用隐式对象
433f = ->
434 return
435 * 1
436 * 2
437 * 3
438
439-- 表格时使用隐式对象
440tb =
441 name: "abc"
442
443 values:
444 - "a"
445 - "b"
446 - "c"
447
448 objects:
449 - name: "a"
450 value: 1
451 func: => @value + 1
452 tb:
453 fieldA: 1
454
455 - name: "b"
456 value: 2
457 func: => @value + 2
458 tb: { }
459```
460
461</YueDisplay>
diff --git a/doc/docs/zh/doc/switch.md b/doc/docs/zh/doc/switch.md
new file mode 100644
index 0000000..700bc2a
--- /dev/null
+++ b/doc/docs/zh/doc/switch.md
@@ -0,0 +1,296 @@
1# switch 语句
2
3&emsp;&emsp;switch 语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和 if 语句一样,switch 语句在最后可以接一个 else 代码块来处理没有匹配的情况。在生成的 Lua 代码中,进行比较是使用 == 操作符完成的。switch 语句中也可以使用赋值表达式来储存临时变量值。
4
5```yuescript
6switch name := "Dan"
7 when "Robert"
8 print "你是Robert"
9 when "Dan", "Daniel"
10 print "你的名字是Dan"
11 else
12 print "我不认识你,你的名字是#{name}"
13```
14<YueDisplay>
15
16```yue
17switch name := "Dan"
18 when "Robert"
19 print "你是Robert"
20 when "Dan", "Daniel"
21 print "你的名字是Dan"
22 else
23 print "我不认识你,你的名字是#{name}"
24```
25
26</YueDisplay>
27
28&emsp;&emsp;switch 语句的 when 子句中可以通过使用逗号分隔的列表来匹配多个值。
29
30&emsp;&emsp;switch 语句也可以作为表达式使用,下面我们可以将 switch 语句返回的结果分配给一个变量:
31
32```yuescript
33b = 1
34next_number = switch b
35 when 1
36 2
37 when 2
38 3
39 else
40 error "数字数得太大了!"
41```
42<YueDisplay>
43
44```yue
45b = 1
46next_number = switch b
47 when 1
48 2
49 when 2
50 3
51 else
52 error "数字数得太大了!"
53```
54
55</YueDisplay>
56
57&emsp;&emsp;我们可以使用 then 关键字在 when 子句的同一行上编写处理代码。else 代码块的后续代码中要写在同一行上不需要额外的关键字。
58
59```yuescript
60msg = switch math.random(1, 5)
61 when 1 then "你很幸运"
62 when 2 then "你差点很幸运"
63 else "不太幸运"
64```
65<YueDisplay>
66
67```yue
68msg = switch math.random(1, 5)
69 when 1 then "你很幸运"
70 when 2 then "你差点很幸运"
71 else "不太幸运"
72```
73
74</YueDisplay>
75
76&emsp;&emsp;如果在编写 switch 语句时希望少写一个缩进,那么你可以把第一个 when 子句放在 switch 开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。
77
78```yuescript
79switch math.random(1, 5)
80 when 1
81 print "你很幸运" -- 两个缩进级别
82 else
83 print "不太幸运"
84
85switch math.random(1, 5) when 1
86 print "你很幸运" -- 一个缩进级别
87else
88 print "不太幸运"
89```
90<YueDisplay>
91
92```yue
93switch math.random(1, 5)
94 when 1
95 print "你很幸运" -- 两个缩进级别
96 else
97 print "不太幸运"
98
99switch math.random(1, 5) when 1
100 print "你很幸运" -- 一个缩进级别
101else
102 print "不太幸运"
103```
104
105</YueDisplay>
106
107&emsp;&emsp;值得注意的是,在生成 Lua 代码时,我们要做检查的目标变量会放在 == 表达式的右侧。当你希望给 when 子句的比较对象定义一个 \_\_eq 元方法来重载判断逻辑时,可能会有用。
108
109## 表格匹配
110
111&emsp;&emsp;在 switch 的 when 子句中,如果期待检查目标是一个表格,且可以通过特定的结构进行解构并获得非 nil 值,那么你可以尝试使用表格匹配的语法。
112
113```yuescript
114items =
115 * x: 100
116 y: 200
117 * width: 300
118 height: 400
119
120for item in *items
121 switch item
122 when :x, :y
123 print "Vec2 #{x}, #{y}"
124 when :width, :height
125 print "尺寸 #{width}, #{height}"
126```
127<YueDisplay>
128
129```yue
130items =
131 * x: 100
132 y: 200
133 * width: 300
134 height: 400
135
136for item in *items
137 switch item
138 when :x, :y
139 print "Vec2 #{x}, #{y}"
140 when :width, :height
141 print "尺寸 #{width}, #{height}"
142```
143
144</YueDisplay>
145
146&emsp;&emsp;你可以使用默认值来选择性地解构表格的某些字段。
147
148```yuescript
149item = {}
150
151{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos')
152
153switch item
154 when {pos: {:x = 50, :y = 200}}
155 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过
156```
157<YueDisplay>
158
159```yue
160item = {}
161
162{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos')
163
164switch item
165 when {pos: {:x = 50, :y = 200}}
166 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过
167```
168
169</YueDisplay>
170
171&emsp;&emsp;你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。
172
173&emsp;&emsp;匹配数组元素。
174
175```yuescript
176switch tb
177 when [1, 2, 3]
178 print "1, 2, 3"
179 when [1, b, 3]
180 print "1, #{b}, 3"
181 when [1, 2, b = 3] -- 变量b有默认值
182 print "1, 2, #{b}"
183```
184<YueDisplay>
185
186```yue
187switch tb
188 when [1, 2, 3]
189 print "1, 2, 3"
190 when [1, b, 3]
191 print "1, #{b}, 3"
192 when [1, 2, b = 3] -- 变量b有默认值
193 print "1, 2, #{b}"
194```
195
196</YueDisplay>
197
198&emsp;&emsp;匹配表格字段。
199
200```yuescript
201switch tb
202 when success: true, :result
203 print "成功", result
204 when success: false
205 print "失败", result
206 else
207 print "无效值"
208```
209<YueDisplay>
210
211```yue
212switch tb
213 when success: true, :result
214 print "成功", result
215 when success: false
216 print "失败", result
217 else
218 print "无效值"
219```
220
221</YueDisplay>
222
223&emsp;&emsp;匹配嵌套的表格结构。
224
225```yuescript
226switch tb
227 when data: {type: "success", :content}
228 print "成功", content
229 when data: {type: "error", :content}
230 print "失败", content
231 else
232 print "无效值"
233```
234<YueDisplay>
235
236```yue
237switch tb
238 when data: {type: "success", :content}
239 print "成功", content
240 when data: {type: "error", :content}
241 print "失败", content
242 else
243 print "无效值"
244```
245
246</YueDisplay>
247
248&emsp;&emsp;匹配表格数组。
249
250```yuescript
251switch tb
252 when [
253 {a: 1, b: 2}
254 {a: 3, b: 4}
255 {a: 5, b: 6}
256 fourth
257 ]
258 print "匹配成功", fourth
259```
260<YueDisplay>
261
262```yue
263switch tb
264 when [
265 {a: 1, b: 2}
266 {a: 3, b: 4}
267 {a: 5, b: 6}
268 fourth
269 ]
270 print "匹配成功", fourth
271```
272
273</YueDisplay>
274
275&emsp;&emsp;匹配一个列表并捕获特定范围内的元素。
276
277```yuescript
278segments = ["admin", "users", "logs", "view"]
279switch segments
280 when [...groups, resource, action]
281 print "Group:", groups -- 打印: {"admin", "users"}
282 print "Resource:", resource -- 打印: "logs"
283 print "Action:", action -- 打印: "view"
284```
285<YueDisplay>
286
287```yue
288segments = ["admin", "users", "logs", "view"]
289switch segments
290 when [...groups, resource, action]
291 print "Group:", groups -- 打印: {"admin", "users"}
292 print "Resource:", resource -- 打印: "logs"
293 print "Action:", action -- 打印: "view"
294```
295
296</YueDisplay>
diff --git a/doc/docs/zh/doc/table-literals.md b/doc/docs/zh/doc/table-literals.md
new file mode 100644
index 0000000..a111950
--- /dev/null
+++ b/doc/docs/zh/doc/table-literals.md
@@ -0,0 +1,168 @@
1# 表格字面量
2
3&emsp;&emsp;和 Lua 一样,表格可以通过花括号进行定义。
4
5```yuescript
6some_values = [1, 2, 3, 4]
7```
8<YueDisplay>
9
10```yue
11some_values = [1, 2, 3, 4]
12```
13
14</YueDisplay>
15
16&emsp;&emsp;但与Lua不同的是,给表格中的键赋值是用 **:**(而不是 **=**)。
17
18```yuescript
19some_values = {
20 name: "Bill",
21 age: 200,
22 ["favorite food"]: "rice"
23}
24```
25<YueDisplay>
26
27```yue
28some_values = {
29 name: "Bill",
30 age: 200,
31 ["favorite food"]: "rice"
32}
33```
34
35</YueDisplay>
36
37&emsp;&emsp;如果只分配一个键值对的表格,可以省略花括号。
38
39```yuescript
40profile =
41 height: "4英尺",
42 shoe_size: 13,
43 favorite_foods: ["冰淇淋", "甜甜圈"]
44```
45<YueDisplay>
46
47```yue
48profile =
49 height: "4英尺",
50 shoe_size: 13,
51 favorite_foods: ["冰淇淋", "甜甜圈"]
52```
53
54</YueDisplay>
55
56&emsp;&emsp;可以使用换行符而不使用逗号(或两者都用)来分隔表格中的值:
57
58```yuescript
59values = {
60 1, 2, 3, 4
61 5, 6, 7, 8
62 name: "超人"
63 occupation: "打击犯罪"
64}
65```
66<YueDisplay>
67
68```yue
69values = {
70 1, 2, 3, 4
71 5, 6, 7, 8
72 name: "超人"
73 occupation: "打击犯罪"
74}
75```
76
77</YueDisplay>
78
79&emsp;&emsp;创建单行表格字面量时,也可以省略花括号:
80
81```yuescript
82my_function dance: "探戈", partner: "无"
83
84y = type: "狗", legs: 4, tails: 1
85```
86<YueDisplay>
87
88```yue
89my_function dance: "探戈", partner: "无"
90
91y = type: "狗", legs: 4, tails: 1
92```
93
94</YueDisplay>
95
96&emsp;&emsp;表格字面量的键可以使用 Lua 语言的关键字,而无需转义:
97
98```yuescript
99tbl = {
100 do: "某事"
101 end: "饥饿"
102}
103```
104<YueDisplay>
105
106```yue
107tbl = {
108 do: "某事"
109 end: "饥饿"
110}
111```
112
113</YueDisplay>
114
115&emsp;&emsp;如果你要构造一个由变量组成的表,并希望键与变量名相同,那么可以使用 **:** 前缀操作符:
116
117```yuescript
118hair = "金色"
119height = 200
120person = { :hair, :height, shoe_size: 40 }
121
122print_table :hair, :height
123```
124<YueDisplay>
125
126```yue
127hair = "金色"
128height = 200
129person = { :hair, :height, shoe_size: 40 }
130
131print_table :hair, :height
132```
133
134</YueDisplay>
135
136&emsp;&emsp;如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在 Lua 中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。
137
138```yuescript
139t = {
140 [1 + 2]: "你好"
141 "你好 世界": true
142}
143```
144<YueDisplay>
145
146```yue
147t = {
148 [1 + 2]: "你好"
149 "你好 世界": true
150}
151```
152
153</YueDisplay>
154
155&emsp;&emsp;Lua 的表同时具有数组部分和哈希部分,但有时候你会希望在书写 Lua 表时,对 Lua 表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。
156
157```yuescript
158some_values = [ 1, 2, 3, 4 ]
159list_with_one_element = [ 1, ]
160```
161<YueDisplay>
162
163```yue
164some_values = [ 1, 2, 3, 4 ]
165list_with_one_element = [ 1, ]
166```
167
168</YueDisplay>
diff --git a/doc/docs/zh/doc/the-using-clause-controlling-destructive-assignment.md b/doc/docs/zh/doc/the-using-clause-controlling-destructive-assignment.md
new file mode 100644
index 0000000..722de6f
--- /dev/null
+++ b/doc/docs/zh/doc/the-using-clause-controlling-destructive-assignment.md
@@ -0,0 +1,98 @@
1# 使用 using 语句:防止破坏性赋值
2
3&emsp;&emsp;Lua 的变量作用域是降低代码复杂度的重要工具。然而,随着代码量的增加,维护这些变量可能变得更加困难。比如,看看下面的代码片段:
4
5```yuescript
6i = 100
7
8-- 许多代码行...
9
10my_func = ->
11 i = 10
12 while i > 0
13 print i
14 i -= 1
15
16my_func!
17
18print i -- 将打印 0
19```
20<YueDisplay>
21
22```yue
23i = 100
24
25-- 许多代码行...
26
27my_func = ->
28 i = 10
29 while i > 0
30 print i
31 i -= 1
32
33my_func!
34
35print i -- 将打印 0
36```
37
38</YueDisplay>
39
40&emsp;&emsp;在 `my_func` 中,我们不小心覆盖了变量 `i` 的值。虽然在这个例子中这个问题很明显,但在一个庞大的或者是由多人共同维护的代码库中,很难追踪每个变量的声明情况。
41
42&emsp;&emsp;如果我们可以明确指出哪些变量是我们想在当前作用域内修改的,并且防止我们不小心更改了其他作用域中同名的变量,那将大有裨益。
43
44&emsp;&emsp;`using` 语句就是为此而生。`using nil` 确保函数内部的赋值不会意外地影响到外部作用域的变量。我们只需将 `using` 子句放在函数的参数列表之后;若函数没有参数,则直接放在括号内即可。
45
46```yuescript
47i = 100
48
49my_func = (using nil) ->
50 i = "hello" -- 这里创建了一个新的局部变量
51
52my_func!
53print i -- 打印 100,i 没有受到影响
54```
55<YueDisplay>
56
57```yue
58i = 100
59
60my_func = (using nil) ->
61 i = "hello" -- 这里创建了一个新的局部变量
62
63my_func!
64print i -- 打印 100,i 没有受到影响
65```
66
67</YueDisplay>
68
69&emsp;&emsp;using子句中可以填写多个用逗号分隔名称。指定可以访问和修改的外部变量的名称:
70
71```yuescript
72tmp = 1213
73i, k = 100, 50
74
75my_func = (add using k, i) ->
76 tmp = tmp + add -- 创建了一个新的局部tmp
77 i += tmp
78 k += tmp
79
80my_func(22)
81print i, k -- 这些已经被更新
82```
83<YueDisplay>
84
85```yue
86tmp = 1213
87i, k = 100, 50
88
89my_func = (add using k, i) ->
90 tmp = tmp + add -- 创建了一个新的局部tmp
91 i += tmp
92 k += tmp
93
94my_func(22)
95print i, k -- 这些已经被更新
96```
97
98</YueDisplay>
diff --git a/doc/docs/zh/doc/the-yuescript-library.md b/doc/docs/zh/doc/the-yuescript-library.md
new file mode 100644
index 0000000..54e26f7
--- /dev/null
+++ b/doc/docs/zh/doc/the-yuescript-library.md
@@ -0,0 +1,821 @@
1# 月之脚本语言库
2
3在 Lua 中使用 `local yue = require("yue")` 来访问。
4
5## yue
6
7**描述:**
8
9月之脚本语言库。
10
11### version
12
13**类型:** 成员变量。
14
15**描述:**
16
17月之脚本版本。
18
19**签名:**
20```lua
21version: string
22```
23
24### dirsep
25
26**类型:** 成员变量。
27
28**描述:**
29
30当前平台的文件分隔符。
31
32**签名:**
33```lua
34dirsep: string
35```
36
37### yue_compiled
38
39**类型:** 成员变量。
40
41**描述:**
42
43编译模块代码缓存。
44
45**签名:**
46```lua
47yue_compiled: {string: string}
48```
49
50### to_lua
51
52**类型:** 函数。
53
54**描述:**
55
56月之脚本的编译函数。它将 YueScript 代码编译为 Lua 代码。
57
58**签名:**
59```lua
60to_lua: function(code: string, config?: Config):
61 --[[codes]] string | nil,
62 --[[error]] string | nil,
63 --[[globals]] {{string, integer, integer}} | nil
64```
65
66**参数:**
67
68| 参数名 | 类型 | 描述 |
69| --- | --- | --- |
70| code | string | YueScript 代码。 |
71| config | Config | [可选] 编译器选项。 |
72
73**返回值:**
74
75| 返回类型 | 描述 |
76| --- | --- |
77| string \| nil | 编译后的 Lua 代码,如果编译失败则为 nil。 |
78| string \| nil | 错误消息,如果编译成功则为 nil。 |
79| {{string, integer, integer}} \| nil | 代码中出现的全局变量(带有名称、行和列),如果编译器选项 `lint_global` 为 false 则为 nil。 |
80
81### file_exist
82
83**类型:** 函数。
84
85**描述:**
86
87检查源文件是否存在的函数。可以覆盖该函数以自定义行为。
88
89**签名:**
90```lua
91file_exist: function(filename: string): boolean
92```
93
94**参数:**
95
96| 参数名 | 类型 | 描述 |
97| --- | --- | --- |
98| filename | string | 文件名。 |
99
100**返回值:**
101
102| 返回类型 | 描述 |
103| --- | --- |
104| boolean | 文件是否存在。 |
105
106### read_file
107
108**类型:** 函数。
109
110**描述:**
111
112读取源文件的函数。可以覆盖该函数以自定义行为。
113
114**签名:**
115```lua
116read_file: function(filename: string): string
117```
118
119**参数:**
120
121| 参数名 | 类型 | 描述 |
122| --- | --- | --- |
123| filename | string | 文件名。 |
124
125**返回值:**
126
127| 返回类型 | 描述 |
128| --- | --- |
129| string | 文件内容。 |
130
131### insert_loader
132
133**类型:** 函数。
134
135**描述:**
136
137将 YueScript 加载器插入到 Lua 包加载器(搜索器)中。
138
139**签名:**
140```lua
141insert_loader: function(pos?: integer): boolean
142```
143
144**参数:**
145
146| 参数名 | 类型 | 描述 |
147| --- | --- | --- |
148| pos | integer | [可选] 要插入加载器的位置。默认为 3。 |
149
150**返回值:**
151
152| 返回类型 | 描述 |
153| --- | --- |
154| boolean | 是否成功插入加载器。如果加载器已经插入,则返回失败。 |
155
156### remove_loader
157
158**类型:** 函数。
159
160**描述:**
161
162从 Lua 包加载器(搜索器)中移除 YueScript 加载器。
163
164**签名:**
165```lua
166remove_loader: function(): boolean
167```
168
169**返回值:**
170
171| 返回类型 | 描述 |
172| --- | --- |
173| boolean | 是否成功移除加载器。如果加载器未插入,则返回失败。 |
174
175### loadstring
176
177**类型:** 函数。
178
179**描述:**
180
181将 YueScript 代码字符串加载为一个函数。
182
183**签名:**
184```lua
185loadstring: function(input: string, chunkname: string, env: table, config?: Config):
186 --[[loaded function]] nil | function(...: any): (any...),
187 --[[error]] string | nil
188```
189
190**参数:**
191
192| 参数名 | 类型 | 描述 |
193| --- | --- | --- |
194| input | string | YueScript 代码。 |
195| chunkname | string | 代码块的名称。 |
196| env | table | 环境表。 |
197| config | Config | [可选] 编译器选项。 |
198
199**返回值:**
200
201| 返回类型 | 描述 |
202| --- | --- |
203| function \| nil | 加载的函数,如果加载失败则为 nil。 |
204| string \| nil | 错误消息,如果加载成功则为 nil。 |
205
206### loadstring
207
208**类型:** 函数。
209
210**描述:**
211
212将 YueScript 代码字符串加载为一个函数。
213
214**签名:**
215```lua
216loadstring: function(input: string, chunkname: string, config?: Config):
217 --[[loaded function]] nil | function(...: any): (any...),
218 --[[error]] string | nil
219```
220
221**参数:**
222
223| 参数名 | 类型 | 描述 |
224| --- | --- | --- |
225| input | string | YueScript 代码。 |
226| chunkname | string | 代码块的名称。 |
227| config | Config | [可选] 编译器选项。 |
228
229**返回值:**
230
231| 返回类型 | 描述 |
232| --- | --- |
233| function \| nil | 加载的函数,如果加载失败则为 nil。 |
234| string \| nil | 错误消息,如果加载成功则为 nil。 |
235
236### loadstring
237
238**类型:** 函数。
239
240**描述:**
241
242将 YueScript 代码字符串加载为一个函数。
243
244**签名:**
245```lua
246loadstring: function(input: string, config?: Config):
247 --[[loaded function]] nil | function(...: any): (any...),
248 --[[error]] string | nil
249```
250
251**参数:**
252
253| 参数名 | 类型 | 描述 |
254| --- | --- | --- |
255| input | string | YueScript 代码。 |
256| config | Config | [可选] 编译器选项。 |
257
258**返回值:**
259
260| 返回类型 | 描述 |
261| --- | --- |
262| function \| nil | 加载的函数,如果加载失败则为 nil。 |
263| string \| nil | 错误消息,如果加载成功则为 nil。 |
264
265### loadfile
266
267**类型:** 函数。
268
269**描述:**
270
271将 YueScript 代码文件加载为一个函数。
272
273**签名:**
274```lua
275loadfile: function(filename: string, env: table, config?: Config):
276 nil | function(...: any): (any...),
277 string | nil
278```
279
280**参数:**
281
282| 参数名 | 类型 | 描述 |
283| --- | --- | --- |
284| filename | string | 文件名。 |
285| env | table | 环境表。 |
286| config | Config | [可选] 编译器选项。 |
287
288**返回值:**
289
290| 返回类型 | 描述 |
291| --- | --- |
292| function \| nil | 加载的函数,如果加载失败则为 nil。 |
293| string \| nil | 错误消息,如果加载成功则为 nil。 |
294
295### loadfile
296
297**类型:** 函数。
298
299**描述:**
300
301将 YueScript 代码文件加载为一个函数。
302
303**签名:**
304```lua
305loadfile: function(filename: string, config?: Config):
306 nil | function(...: any): (any...),
307 string | nil
308```
309
310**参数:**
311
312| 参数名 | 类型 | 描述 |
313| --- | --- | --- |
314| filename | string | 文件名。 |
315| config | Config | [可选] 编译器选项。 |
316
317**返回值:**
318
319| 返回类型 | 描述 |
320| --- | --- |
321| function \| nil | 加载的函数,如果加载失败则为 nil。 |
322| string \| nil | 错误消息,如果加载成功则为 nil。 |
323
324### dofile
325
326**类型:** 函数。
327
328**描述:**
329
330将 YueScript 代码文件加载为一个函数并执行。
331
332**签名:**
333```lua
334dofile: function(filename: string, env: table, config?: Config): any...
335```
336
337**参数:**
338
339| 参数名 | 类型 | 描述 |
340| --- | --- | --- |
341| filename | string | 文件名。 |
342| env | table | 环境表。 |
343| config | Config | [可选] 编译器选项。 |
344
345**返回值:**
346
347| 返回类型 | 描述 |
348| --- | --- |
349| any... | 加载的函数执行后的返回值。 |
350
351### dofile
352
353**类型:** 函数。
354
355**描述:**
356
357将 YueScript 代码文件加载为一个函数并执行。
358
359**签名:**
360```lua
361dofile: function(filename: string, config?: Config): any...
362```
363
364**参数:**
365
366| 参数名 | 类型 | 描述 |
367| --- | --- | --- |
368| filename | string | 文件名。 |
369| config | Config | [可选] 编译器选项。 |
370
371**返回值:**
372
373| 返回类型 | 描述 |
374| --- | --- |
375| any... | 加载的函数执行后的返回值。 |
376
377### find_modulepath
378
379**类型:** 函数。
380
381**描述:**
382
383将 YueScript 模块名解析为文件路径。
384
385**签名:**
386```lua
387find_modulepath: function(name: string): string
388```
389
390**参数:**
391
392| 参数名 | 类型 | 描述 |
393| --- | --- | --- |
394| name | string | 模块名。 |
395
396**返回值:**
397
398| 返回类型 | 描述 |
399| --- | --- |
400| string | 文件路径。 |
401
402### pcall
403
404**类型:** 函数。
405
406**描述:**
407
408在保护模式下调用一个函数。
409会捕获任何错误,执行成功则返回成功状态和结果,否则为失败状态和错误信息。
410当发生错误时,将错误信息中的代码行号重写为 YueScript 代码中的原始行号。
411
412**签名:**
413```lua
414pcall: function(f: function, ...: any): boolean, any...
415```
416
417**参数:**
418
419| 参数名 | 类型 | 描述 |
420| --- | --- | --- |
421| f | function | 要调用的函数。 |
422| ... | any | 要传递给函数的参数。 |
423
424**返回值:**
425
426| 返回类型 | 描述 |
427| --- | --- |
428| boolean, ... | 状态码和函数结果或错误信息。 |
429
430### require
431
432**类型:** 函数。
433
434**描述:**
435
436加载给定的模块。可以是 Lua 模块或 YueScript 模块。
437如果模块是 YueScript 模块且加载失败,则将错误信息中的代码行号重写为 YueScript 代码中的原始行号。
438
439**签名:**
440```lua
441require: function(name: string): any...
442```
443
444**参数:**
445
446| 参数名 | 类型 | 描述 |
447| --- | --- | --- |
448| modname | string | 要加载的模块名。 |
449
450**返回值:**
451
452| 返回类型 | 描述 |
453| --- | --- |
454| any | 如果模块已经加载,则返回 package.loaded[modname] 中存储的值。否则,尝试查找加载器并返回 package.loaded[modname] 的最终值和加载器数据作为第二个结果。 |
455
456### p
457
458**类型:** 函数。
459
460**描述:**
461
462检查传递的值的内部结构,并打印值出它的字符串表示。
463
464**签名:**
465```lua
466p: function(...: any)
467```
468
469**参数:**
470
471| 参数名 | 类型 | 描述 |
472| --- | --- | --- |
473| ... | any | 要检查的值。 |
474
475### options
476
477**类型:** 成员变量。
478
479**描述:**
480
481当前编译器选项。
482
483**签名:**
484```lua
485options: Config.Options
486```
487
488### traceback
489
490**类型:** 函数。
491
492**描述:**
493
494重写堆栈跟踪中的行号为 YueScript 代码中的原始行号的 traceback 函数。
495
496**签名:**
497```lua
498traceback: function(message: string): string
499```
500
501**参数:**
502
503| 参数名 | 类型 | 描述 |
504| --- | --- | --- |
505| message | string | 堆栈跟踪消息。 |
506
507**返回值:**
508
509| 返回类型 | 描述 |
510| --- | --- |
511| string | 重写后的堆栈跟踪消息。 |
512
513### is_ast
514
515**类型:** 函数。
516
517**描述:**
518
519检查代码是否匹配指定的 AST。
520
521**签名:**
522```lua
523is_ast: function(astName: string, code: string): boolean
524```
525
526**参数:**
527
528| 参数名 | 类型 | 描述 |
529| --- | --- | --- |
530| astName | string | AST 名称。 |
531| code | string | 代码。 |
532
533**返回值:**
534
535| 返回类型 | 描述 |
536| --- | --- |
537| boolean | 代码是否匹配 AST。 |
538
539### AST
540
541**类型:** 成员变量。
542
543**描述:**
544
545AST 类型定义,带有名称、行、列和子节点。
546
547**签名:**
548```lua
549type AST = {string, integer, integer, any}
550```
551
552### to_ast
553
554**类型:** 函数。
555
556**描述:**
557
558将代码转换为 AST。
559
560**签名:**
561```lua
562to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean):
563 --[[AST]] AST | nil,
564 --[[error]] nil | string
565```
566
567**参数:**
568
569| 参数名 | 类型 | 描述 |
570| --- | --- | --- |
571| code | string | 代码。 |
572| flattenLevel | integer | [可选] 扁平化级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 |
573| astName | string | [可选] AST 名称。默认为 "File"。 |
574| reserveComment | boolean | [可选] 是否保留原始注释。默认为 false。 |
575
576**返回值:**
577
578| 返回类型 | 描述 |
579| --- | --- |
580| AST \| nil | AST,如果转换失败则为 nil。 |
581| string \| nil | 错误消息,如果转换成功则为 nil。 |
582
583### format
584
585**类型:** 函数。
586
587**描述:**
588
589格式化 YueScript 代码。
590
591**签名:**
592```lua
593format: function(code: string, tabSize?: number, reserveComment?: boolean): string
594```
595
596**参数:**
597
598| 参数名 | 类型 | 描述 |
599| --- | --- | --- |
600| code | string | 代码。 |
601| tabSize | integer | [可选] 制表符大小。默认为 4。 |
602| reserveComment | boolean | [可选] 是否保留原始注释。默认为 true。 |
603
604**返回值:**
605
606| 返回类型 | 描述 |
607| --- | --- |
608| string | 格式化后的代码。 |
609
610### __call
611
612**类型:** 元方法。
613
614**描述:**
615
616导入 YueScript 模块。
617如果发生加载失败,则将错误信息中的代码行号重写为 YueScript 代码中的原始行号。
618
619**签名:**
620```lua
621metamethod __call: function(self: yue, module: string): any...
622```
623
624**参数:**
625
626| 参数名 | 类型 | 描述 |
627| --- | --- | --- |
628| module | string | 模块名。 |
629
630**返回值:**
631
632| 返回类型 | 描述 |
633| --- | --- |
634| any | 模块值。 |
635
636## Config
637
638**描述:**
639
640编译器编译选项。
641
642### lint_global
643
644**类型:** 成员变量。
645
646**描述:**
647
648编译器是否应该收集代码中出现的全局变量。
649
650**签名:**
651```lua
652lint_global: boolean
653```
654
655### implicit_return_root
656
657**类型:** 成员变量。
658
659**描述:**
660
661编译器是否应该对根层级的代码块进行隐式的表达式返回。
662
663**签名:**
664```lua
665implicit_return_root: boolean
666```
667
668### reserve_line_number
669
670**类型:** 成员变量。
671
672**描述:**
673
674编译器是否应该在编译后的代码中保留原始行号。
675
676**签名:**
677```lua
678reserve_line_number: boolean
679```
680
681### reserve_comment
682
683**类型:** 成员变量。
684
685**描述:**
686
687编译器是否应该在编译后的代码中保留原始注释。
688
689**签名:**
690```lua
691reserve_comment: boolean
692```
693
694### space_over_tab
695
696**类型:** 成员变量。
697
698**描述:**
699
700编译器是否应该在编译后的代码中使用空格字符而不是制表符字符。
701
702**签名:**
703```lua
704space_over_tab: boolean
705```
706
707### same_module
708
709**类型:** 成员变量。
710
711**描述:**
712
713编译器是否应该将要编译的代码视为当前正在编译的模块。仅供编译器内部使用。
714
715**签名:**
716```lua
717same_module: boolean
718```
719
720### line_offset
721
722**类型:** 成员变量。
723
724**描述:**
725
726编译器错误消息是否应该包含行号偏移量。仅供编译器内部使用。
727
728**签名:**
729```lua
730line_offset: integer
731```
732
733### yue.Config.LuaTarget
734
735**类型:** 枚举。
736
737**描述:**
738
739目标 Lua 版本枚举。
740
741**签名:**
742```lua
743enum LuaTarget
744 "5.1"
745 "5.2"
746 "5.3"
747 "5.4"
748 "5.5"
749end
750```
751
752### options
753
754**类型:** 成员变量。
755
756**描述:**
757
758要传递给编译函数的额外选项。
759
760**签名:**
761```lua
762options: Options
763```
764
765## Options
766
767**描述:**
768
769额外编译器选项定义。
770
771### target
772
773**类型:** 成员变量。
774
775**描述:**
776
777编译目标 Lua 版本。
778
779**签名:**
780```lua
781target: LuaTarget
782```
783
784### path
785
786**类型:** 成员变量。
787
788**描述:**
789
790额外模块搜索路径。
791
792**签名:**
793```lua
794path: string
795```
796
797### dump_locals
798
799**类型:** 成员变量。
800
801**描述:**
802
803是否在回溯错误消息中输出代码块的局部变量。默认为 false。
804
805**签名:**
806```lua
807dump_locals: boolean
808```
809
810### simplified
811
812**类型:** 成员变量。
813
814**描述:**
815
816是否简化输出的错误消息。默认为 true。
817
818**签名:**
819```lua
820simplified: boolean
821```
diff --git a/doc/docs/zh/doc/try.md b/doc/docs/zh/doc/try.md
new file mode 100644
index 0000000..b4de24d
--- /dev/null
+++ b/doc/docs/zh/doc/try.md
@@ -0,0 +1,105 @@
1# 错误处理
2
3&emsp;&emsp;用于统一进行 Lua 错误处理的便捷语法。
4
5```yuescript
6try
7 func 1, 2, 3
8catch err
9 print yue.traceback err
10
11success, result = try
12 func 1, 2, 3
13catch err
14 yue.traceback err
15
16try func 1, 2, 3
17catch err
18 print yue.traceback err
19
20success, result = try func 1, 2, 3
21
22try
23 print "尝试中"
24 func 1, 2, 3
25
26-- 使用if赋值模式
27if success, result := try func 1, 2, 3
28catch err
29 print yue.traceback err
30 print result
31```
32<YueDisplay>
33
34```yue
35try
36 func 1, 2, 3
37catch err
38 print yue.traceback err
39
40success, result = try
41 func 1, 2, 3
42catch err
43 yue.traceback err
44
45try func 1, 2, 3
46catch err
47 print yue.traceback err
48
49success, result = try func 1, 2, 3
50
51try
52 print "尝试中"
53 func 1, 2, 3
54
55-- 使用if赋值模式
56if success, result := try func 1, 2, 3
57catch err
58 print yue.traceback err
59 print result
60```
61
62</YueDisplay>
63
64## 错误处理简化
65
66&emsp;&emsp;`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。
67
68```yuescript
69a, b, c = try? func!
70
71-- 与空值合并运算符一起使用
72a = (try? func!) ?? "default"
73
74-- 作为函数参数
75f try? func!
76
77-- 带 catch 块的 try!
78f try?
79 print 123
80 func!
81catch e
82 print e
83 e
84```
85<YueDisplay>
86
87```yue
88a, b, c = try? func!
89
90-- 与空值合并运算符一起使用
91a = (try? func!) ?? "default"
92
93-- 作为函数参数
94f try? func!
95
96-- 带 catch 块的 try!
97f try?
98 print 123
99 func!
100catch e
101 print e
102 e
103```
104
105</YueDisplay>
diff --git a/doc/docs/zh/doc/usage.md b/doc/docs/zh/doc/usage.md
new file mode 100644
index 0000000..b9d84d4
--- /dev/null
+++ b/doc/docs/zh/doc/usage.md
@@ -0,0 +1,110 @@
1# 使用方法
2
3## Lua 模块
4
5&emsp;&emsp;在 Lua 中使用月之脚本模块:
6
7* **用法 1**
8
9 &emsp;&emsp;在 Lua 中引入 "你的脚本入口文件.yue"。
10
11 ```Lua
12 require("yue")("你的脚本入口文件")
13 ```
14
15 &emsp;&emsp;当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import** 进行脚本引用即可。错误消息中的代码行号也会被正确处理。
16
17* **用法 2**
18
19 &emsp;&emsp;手动引入月之脚本模块并重写错误消息来帮助调试。
20 ```lua
21 local yue = require("yue")
22 yue.insert_loaders()
23 local success, result = xpcall(function()
24 return require("yuescript_module_name")
25 end, function(err)
26 return yue.traceback(err)
27 end)
28 ```
29
30* **用法 3**
31
32 &emsp;&emsp;在 Lua 中使用月之脚本编译器功能。
33 ```lua
34 local yue = require("yue")
35 local codes, err, globals = yue.to_lua([[
36 f = ->
37 print "hello world"
38 f!
39 ]],{
40 implicit_return_root = true,
41 reserve_line_number = true,
42 lint_global = true,
43 space_over_tab = false,
44 options = {
45 target = "5.4",
46 path = "/script"
47 }
48 })
49 ```
50
51## 月之脚本编译工具
52
53&emsp;&emsp;使用月之脚本编译工具:
54
55```shell
56> yue -h
57命令行用法: yue
58 [选项] [<文件/目录>] ...
59 yue -e <代码或文件> [参数...]
60 yue -w [<目录>] [选项]
61 yue -
62
63说明:
64 - '-' 或 '--' 必须作为唯一且第一个参数,用于读取标准输入。
65 - '-o/--output' 不能与多个输入文件一起使用。
66 - '-w/--watch' 仅能用于目录,不能用于单个文件。
67 - 使用 '-e/--execute' 时,后续的参数将作为脚本参数传递。
68
69选项:
70 -h, --help 显示帮助信息并退出
71 -e <字符串>, --execute <字符串> 执行文件或原始代码
72 -m, --minify 生成压缩(最小化)代码
73 -r, --rewrite 重写输出以匹配原始代码行号
74 -t <目标路径>, --output-to <目标路径>
75 指定编译后文件的输出路径
76 -o <文件>, --output <文件> 将输出写入文件
77 -p, --print 输出到标准输出
78 -b, --benchmark 输出编译耗时(不写入文件)
79 -g, --globals 显示用到的全局变量及其所在的名称、行号、列号
80 -s, --spaces 用空格代替制表符(tab)输出代码
81 -l, --line-numbers 输出源代码的行号
82 -j, --no-implicit-return 禁用文件末尾的隐式返回
83 -c, --reserve-comments 保留源代码中的注释
84 -w [<目录>], --watch [<目录>]
85 监视目录变化并自动编译
86 -v, --version 显示版本信息
87 - 从标准输入读取,输出到标准输出(仅能作为唯一参数)
88 -- 等同于 '-',为兼容旧版本保留
89
90 --target <版本> 指定生成代码的 Lua 版本 (只能为 5.1 ~ 5.5)
91 --path <路径字符串> 附加一个 Lua 搜索路径到 package.path
92 --<键>=<值> 以 key=value 形式传递编译器选项(保持已有用法)
93
94 不带选项直接运行可进入交互模式(REPL),在交互模式里输入单独的符号 '$'
95 可用于开始或结束多行模式。
96```
97
98&emsp;&emsp;使用案例:
99
100&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .**
101
102&emsp;&emsp;编译并将结果保存到目标路径: **yue -t /target/path/ .**
103
104&emsp;&emsp;编译并保留调试信息: **yue -l .**
105
106&emsp;&emsp;编译并生成压缩代码: **yue -m .**
107
108&emsp;&emsp;直接执行代码: **yue -e 'print 123'**
109
110&emsp;&emsp;执行一个月之脚本文件: **yue -e main.yue**
diff --git a/doc/docs/zh/doc/varargs-assignment.md b/doc/docs/zh/doc/varargs-assignment.md
new file mode 100644
index 0000000..6cc4278
--- /dev/null
+++ b/doc/docs/zh/doc/varargs-assignment.md
@@ -0,0 +1,24 @@
1# 可变参数赋值
2
3&emsp;&emsp;你可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用 Lua 的方式访问其内容。
4
5```yuescript
6list = [1, 2, 3, 4, 5]
7fn = (ok) -> ok, table.unpack list
8ok, ... = fn true
9count = select '#', ...
10first = select 1, ...
11print ok, count, first
12```
13<YueDisplay>
14
15```yue
16list = [1, 2, 3, 4, 5]
17fn = (ok) -> ok, table.unpack list
18ok, ... = fn true
19count = select '#', ...
20first = select 1, ...
21print ok, count, first
22```
23
24</YueDisplay>
diff --git a/doc/docs/zh/doc/while-loop.md b/doc/docs/zh/doc/while-loop.md
new file mode 100644
index 0000000..5995890
--- /dev/null
+++ b/doc/docs/zh/doc/while-loop.md
@@ -0,0 +1,69 @@
1# while 循环
2
3&emsp;&emsp;在月之脚本中的 while 循环支持几种不同的写法:
4
5```yuescript
6i = 10
7while i > 0
8 print i
9 i -= 1
10
11while running == true do my_function!
12```
13<YueDisplay>
14
15```yue
16i = 10
17while i > 0
18 print i
19 i -= 1
20
21while running == true do my_function!
22```
23
24</YueDisplay>
25
26```yuescript
27i = 10
28until i == 0
29 print i
30 i -= 1
31
32until running == false do my_function!
33```
34<YueDisplay>
35
36```yue
37i = 10
38until i == 0
39 print i
40 i -= 1
41until running == false do my_function!
42```
43
44</YueDisplay>
45
46&emsp;&emsp;像 for 循环的语法一样,while 循环也可以作为一个表达式使用。为了使函数返回 while 循环的累积列表值,必须明确使用返回语句返回 while 循环表达式。
47
48## repeat 循环
49
50&emsp;&emsp;repeat 循环是从 Lua 语言中搬过来的相似语法:
51
52```yuescript
53i = 10
54repeat
55 print i
56 i -= 1
57until i == 0
58```
59<YueDisplay>
60
61```yue
62i = 10
63repeat
64 print i
65 i -= 1
66until i == 0
67```
68
69</YueDisplay>
diff --git a/doc/docs/zh/doc/whitespace.md b/doc/docs/zh/doc/whitespace.md
new file mode 100644
index 0000000..1886e23
--- /dev/null
+++ b/doc/docs/zh/doc/whitespace.md
@@ -0,0 +1,43 @@
1# 空白
2
3&emsp;&emsp;月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。
4
5## 语句分隔符
6
7&emsp;&emsp;一条语句通常以换行结束。你也可以使用分号 `;` 显式结束一条语句,从而在同一行中编写多条语句:
8
9```yuescript
10a = 1; b = 2; print a + b
11```
12<YueDisplay>
13
14```yue
15a = 1; b = 2; print a + b
16```
17
18</YueDisplay>
19
20## 多行链式调用
21
22&emsp;&emsp;你可以使用相同的缩进来编写多行链式函数调用。
23
24```yuescript
25Rx.Observable
26 .fromRange 1, 8
27 \filter (x) -> x % 2 == 0
28 \concat Rx.Observable.of 'who do we appreciate'
29 \map (value) -> value .. '!'
30 \subscribe print
31```
32<YueDisplay>
33
34```yue
35Rx.Observable
36 .fromRange 1, 8
37 \filter (x) -> x % 2 == 0
38 \concat Rx.Observable.of 'who do we appreciate'
39 \map (value) -> value .. '!'
40 \subscribe print
41```
42
43</YueDisplay>
diff --git a/doc/docs/zh/doc/with-statement.md b/doc/docs/zh/doc/with-statement.md
new file mode 100644
index 0000000..fbd3633
--- /dev/null
+++ b/doc/docs/zh/doc/with-statement.md
@@ -0,0 +1,126 @@
1# with 语句
2
3
4在编写 Lua 代码时,我们在创建对象后的常见操作是立即调用这个对象一系列操作函数并设置一系列属性。
5
6这导致在代码中多次重复引用对象的名称,增加了不必要的文本噪音。一个常见的解决方案是在创建对象时,在构造函数传入一个表,该表包含要覆盖设置的键和值的集合。这样做的缺点是该对象的构造函数必须支持这种初始化形式。
7
8with 块有助于简化编写这样的代码。在 with 块内,我们可以使用以 . 或 \ 开头的特殊语句,这些语句代表我们正在使用的对象的操作。
9
10例如,我们可以这样处理一个新创建的对象:
11
12```yuescript
13with Person!
14 .name = "Oswald"
15 \add_relative my_dad
16 \save!
17 print .name
18```
19<YueDisplay>
20
21```yue
22with Person!
23 .name = "Oswald"
24 \add_relative my_dad
25 \save!
26 print .name
27```
28
29</YueDisplay>
30
31with 语句也可以用作一个表达式,并返回它的代码块正在处理的对象。
32
33```yuescript
34file = with File "favorite_foods.txt"
35 \set_encoding "utf8"
36```
37<YueDisplay>
38
39```yue
40file = with File "favorite_foods.txt"
41 \set_encoding "utf8"
42```
43
44</YueDisplay>
45
46或者…
47
48```yuescript
49create_person = (name, relatives) ->
50 with Person!
51 .name = name
52 \add_relative relative for relative in *relatives
53
54me = create_person "Leaf", [dad, mother, sister]
55```
56<YueDisplay>
57
58```yue
59create_person = (name, relatives) ->
60 with Person!
61 .name = name
62 \add_relative relative for relative in *relatives
63
64me = create_person "Leaf", [dad, mother, sister]
65```
66
67</YueDisplay>
68
69在此用法中,with 可以被视为K组合子(k-combinator)的一种特殊形式。
70
71如果你想给表达式另外起一个名称的话,with 语句中的表达式也可以是一个赋值语句。
72
73```yuescript
74with str := "你好"
75 print "原始:", str
76 print "大写:", \upper!
77```
78<YueDisplay>
79
80```yue
81with str := "你好"
82 print "原始:", str
83 print "大写:", \upper!
84```
85
86</YueDisplay>
87
88你可以在 `with` 语句中使用 `[]` 访问特殊键。
89
90```yuescript
91with tb
92 [1] = 1
93 print [2]
94 with [abc]
95 [3] = [2]\func!
96 ["key-name"] = value
97 [] = "abc" -- 追加到 "tb"
98```
99<YueDisplay>
100
101```yue
102with tb
103 [1] = 1
104 print [2]
105 with [abc]
106 [3] = [2]\func!
107 ["key-name"] = value
108 [] = "abc" -- 追加到 "tb"
109```
110
111</YueDisplay>
112
113`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。
114
115```yuescript
116with? obj
117 print obj.name
118```
119<YueDisplay>
120
121```yue
122with? obj
123 print obj.name
124```
125
126</YueDisplay>
diff --git a/doc/docs/zh/index.md b/doc/docs/zh/index.md
index 9068956..ea42085 100644
--- a/doc/docs/zh/index.md
+++ b/doc/docs/zh/index.md
@@ -17,7 +17,6 @@ features:
17 details: 管道、模式匹配、切片与解构,同时保留 Lua 互操作性。 17 details: 管道、模式匹配、切片与解构,同时保留 Lua 互操作性。
18 - title: 快速迭代 18 - title: 快速迭代
19 details: 虚心接受用户反馈,以帮助改进和加速语言的开发和演进! 19 details: 虚心接受用户反馈,以帮助改进和加速语言的开发和演进!
20footer: MIT Licensed | Copyright © 2017-2026 Li Jin
21--- 20---
22 21
23### 版权和协议 22### 版权和协议
diff --git a/spec/inputs/compile_doc.yue b/spec/inputs/compile_doc.yue
index db0464b..45a0b16 100644
--- a/spec/inputs/compile_doc.yue
+++ b/spec/inputs/compile_doc.yue
@@ -1,24 +1,83 @@
1outputFolder = ... 1outputFolder = ...
2for [compiledFile, docFile] in *[ 2for [compiledFile, docFiles] in *[
3 ["codes_from_doc.lua", "doc/docs/doc/index.md"] 3 ["codes_from_doc.lua", [
4 ["codes_from_doc_zh.lua", "doc/docs/zh/doc/index.md"] 4 "doc/docs/doc/introduction.md"
5 "doc/docs/doc/macro.md"
6 "doc/docs/doc/operator.md"
7 "doc/docs/doc/module.md"
8 "doc/docs/doc/assignment.md"
9 "doc/docs/doc/destructuring-assignment.md"
10 "doc/docs/doc/if-assignment.md"
11 "doc/docs/doc/varargs-assignment.md"
12 "doc/docs/doc/whitespace.md"
13 "doc/docs/doc/comment.md"
14 "doc/docs/doc/try.md"
15 "doc/docs/doc/attributes.md"
16 "doc/docs/doc/literals.md"
17 "doc/docs/doc/function-literals.md"
18 "doc/docs/doc/backcalls.md"
19 "doc/docs/doc/table-literals.md"
20 "doc/docs/doc/comprehensions.md"
21 "doc/docs/doc/for-loop.md"
22 "doc/docs/doc/while-loop.md"
23 "doc/docs/doc/continue.md"
24 "doc/docs/doc/conditionals.md"
25 "doc/docs/doc/line-decorators.md"
26 "doc/docs/doc/switch.md"
27 "doc/docs/doc/object-oriented-programming.md"
28 "doc/docs/doc/with-statement.md"
29 "doc/docs/doc/do.md"
30 "doc/docs/doc/function-stubs.md"
31 "doc/docs/doc/the-using-clause-controlling-destructive-assignment.md"
32 ]]
33 ["codes_from_doc_zh.lua", [
34 "doc/docs/zh/doc/introduction.md"
35 "doc/docs/zh/doc/macro.md"
36 "doc/docs/zh/doc/operator.md"
37 "doc/docs/zh/doc/module.md"
38 "doc/docs/zh/doc/assignment.md"
39 "doc/docs/zh/doc/destructuring-assignment.md"
40 "doc/docs/zh/doc/if-assignment.md"
41 "doc/docs/zh/doc/varargs-assignment.md"
42 "doc/docs/zh/doc/whitespace.md"
43 "doc/docs/zh/doc/comment.md"
44 "doc/docs/zh/doc/try.md"
45 "doc/docs/zh/doc/attributes.md"
46 "doc/docs/zh/doc/literals.md"
47 "doc/docs/zh/doc/function-literals.md"
48 "doc/docs/zh/doc/backcalls.md"
49 "doc/docs/zh/doc/table-literals.md"
50 "doc/docs/zh/doc/comprehensions.md"
51 "doc/docs/zh/doc/for-loop.md"
52 "doc/docs/zh/doc/while-loop.md"
53 "doc/docs/zh/doc/continue.md"
54 "doc/docs/zh/doc/conditionals.md"
55 "doc/docs/zh/doc/line-decorators.md"
56 "doc/docs/zh/doc/switch.md"
57 "doc/docs/zh/doc/object-oriented-programming.md"
58 "doc/docs/zh/doc/with-statement.md"
59 "doc/docs/zh/doc/do.md"
60 "doc/docs/zh/doc/function-stubs.md"
61 "doc/docs/zh/doc/the-using-clause-controlling-destructive-assignment.md"
62 ]]
5 ] 63 ]
6 close input = with? io.open docFile 64 codes = []
7 import "yue" as :to_lua 65 for docFile in *docFiles
8 text = \read "*a" 66 close input = with? io.open docFile
9 codes = [] 67 import "yue" as :to_lua
10 for code in text\gmatch "```yuescript[\r\n]+(.-)```[^%w]" 68 text = \read "*a"
11 if result, err := to_lua code, implicit_return_root: false, reserve_line_number: false 69 for code in text\gmatch "```yuescript[\r\n]+(.-)```[^%w]"
12 codes[] = result 70 if result, err := to_lua code, implicit_return_root: false, reserve_line_number: false
13 elseif not err\match "macro exporting module only accepts macro definition" 71 codes[] = result
14 print err 72 elseif not err\match "macro exporting module only accepts macro definition"
15 os.exit 1 73 print err
16 for code in text\gmatch "```yue[\r\n]+(.-)```[^%w]" 74 os.exit 1
17 if result, err := to_lua code, implicit_return_root: false, reserve_line_number: false 75 for code in text\gmatch "```yue[\r\n]+(.-)```[^%w]"
18 codes[] = result 76 if result, err := to_lua code, implicit_return_root: false, reserve_line_number: false
19 else 77 codes[] = result
20 print err 78 else
21 os.exit 1 79 print err
22 close output = with io.open "#{outputFolder}/#{compiledFile}", "w+" 80 os.exit 1
23 \write table.concat codes 81 close output = with io.open "#{outputFolder}/#{compiledFile}", "w+"
82 \write table.concat codes
24 83
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua
index b8985e7..889105a 100644
--- a/spec/outputs/codes_from_doc.lua
+++ b/spec/outputs/codes_from_doc.lua
@@ -76,6 +76,123 @@ end
76local _u1f31b = "月之脚本" 76local _u1f31b = "月之脚本"
77_module_0["🌛"] = _u1f31b 77_module_0["🌛"] = _u1f31b
78return _module_0 78return _module_0
79local _module_0 = { }
80local p, to_lua
81do
82 local _obj_0 = require("yue")
83 p, to_lua = _obj_0.p, _obj_0.to_lua
84end
85local inventory = {
86 equipment = {
87 "sword",
88 "shield"
89 },
90 items = {
91 {
92 name = "potion",
93 count = 10
94 },
95 {
96 name = "bread",
97 count = 3
98 }
99 }
100}
101local map
102map = function(arr, action)
103 local _accum_0 = { }
104 local _len_0 = 1
105 for _index_0 = 1, #arr do
106 local item = arr[_index_0]
107 _accum_0[_len_0] = action(item)
108 _len_0 = _len_0 + 1
109 end
110 return _accum_0
111end
112local filter
113filter = function(arr, cond)
114 local _accum_0 = { }
115 local _len_0 = 1
116 for _index_0 = 1, #arr do
117 local item = arr[_index_0]
118 if cond(item) then
119 _accum_0[_len_0] = item
120 _len_0 = _len_0 + 1
121 end
122 end
123 return _accum_0
124end
125local reduce
126reduce = function(arr, init, action)
127 for _index_0 = 1, #arr do
128 local item = arr[_index_0]
129 init = action(init, item)
130 end
131 return init
132end
133print(reduce(filter(map({
134 1,
135 2,
136 3
137}, function(x)
138 return x * 2
139end), function(x)
140 return x > 4
141end), 0, function(a, b)
142 return a + b
143end))
144local apple = setmetatable({
145 size = 15,
146}, {
147 __index = {
148 color = 0x00ffff
149 }
150})
151if (getmetatable(apple) ~= nil) then
152 p(apple.size, apple.color, getmetatable(apple).__index)
153end
154local _u1f31b = "月之脚本"
155_module_0["🌛"] = _u1f31b
156return _module_0
157local area = 6.2831853071796 * 5
158print('hello world')
159do
160 assert(item ~= nil)
161end
162local value = item
163if (f1() and f2() and f3()) then
164 print("OK")
165end
166do
167 local funcA
168 funcA = function() end
169end
170local funcA
171funcA = function()
172 return "fail to assign to the Yue macro defined variable"
173end
174do
175local function funcB() end
176end
177local funcB
178funcB = function()
179 return "fail to assign to the Lua macro defined variable"
180end
181do
182-- raw Lua codes insertion
183if cond then
184 print("output")
185end
186end
187print("yuescript")
188print(2)
189print("Valid enum type:", "Static")
190do
191 print(123, "hello")
192end
193do
194 print(123, "hello")
195end
79local area = 6.2831853071796 * 5 196local area = 6.2831853071796 * 5
80print('hello world') 197print('hello world')
81do 198do
@@ -408,6 +525,430 @@ local tb = {
408 } 525 }
409 } 526 }
410} 527}
528if tb ~= nil then
529 tb:func()
530end
531if tb ~= nil then
532 tb:func()
533end
534print(1 < 2 and 2 <= 2 and 2 < 3 and 3 == 3 and 3 > 2 and 2 >= 1 and 1 == 1 and 1 < 3 and 3 ~= 5)
535local a = 5
536print(1 <= a and a <= 10)
537local v
538v = function(x)
539 print(x)
540 return x
541end
542print((function()
543 local _cond_0 = v(2)
544 if not (v(1) < _cond_0) then
545 return false
546 else
547 return _cond_0 <= v(3)
548 end
549end)())
550print((function()
551 local _cond_0 = v(2)
552 if not (v(1) > _cond_0) then
553 return false
554 else
555 return _cond_0 <= v(3)
556 end
557end)())
558local tab = { }
559tab[#tab + 1] = "Value"
560local tbA = {
561 1,
562 2,
563 3
564}
565local tbB = {
566 4,
567 5,
568 6
569}
570local _len_0 = #tbA + 1
571for _index_0 = 1, #tbB do
572 local _elm_0 = tbB[_index_0]
573 tbA[_len_0], _len_0 = _elm_0, _len_0 + 1
574end
575local parts = {
576 "shoulders",
577 "knees"
578}
579local lyrics
580do
581 local _tab_0 = {
582 "head"
583 }
584 local _idx_0 = 1
585 for _key_0, _value_0 in pairs(parts) do
586 if _idx_0 == _key_0 then
587 _tab_0[#_tab_0 + 1] = _value_0
588 _idx_0 = _idx_0 + 1
589 else
590 _tab_0[_key_0] = _value_0
591 end
592 end
593 _tab_0[#_tab_0 + 1] = "and"
594 _tab_0[#_tab_0 + 1] = "toes"
595 lyrics = _tab_0
596end
597local copy
598do
599 local _tab_0 = { }
600 local _idx_0 = 1
601 for _key_0, _value_0 in pairs(other) do
602 if _idx_0 == _key_0 then
603 _tab_0[#_tab_0 + 1] = _value_0
604 _idx_0 = _idx_0 + 1
605 else
606 _tab_0[_key_0] = _value_0
607 end
608 end
609 copy = _tab_0
610end
611local a = {
612 1,
613 2,
614 3,
615 x = 1
616}
617local b = {
618 4,
619 5,
620 y = 1
621}
622local merge
623local _tab_0 = { }
624local _idx_0 = 1
625for _key_0, _value_0 in pairs(a) do
626 if _idx_0 == _key_0 then
627 _tab_0[#_tab_0 + 1] = _value_0
628 _idx_0 = _idx_0 + 1
629 else
630 _tab_0[_key_0] = _value_0
631 end
632end
633local _idx_1 = 1
634for _key_0, _value_0 in pairs(b) do
635 if _idx_1 == _key_0 then
636 _tab_0[#_tab_0 + 1] = _value_0
637 _idx_1 = _idx_1 + 1
638 else
639 _tab_0[_key_0] = _value_0
640 end
641end
642merge = _tab_0
643local last
644do
645 local _item_0 = data.items
646 last = _item_0[#_item_0]
647end
648local second_last
649do
650 local _item_0 = data.items
651 second_last = _item_0[#_item_0 - 1]
652end
653local _obj_0 = data.items
654_obj_0[#_obj_0] = 1
655local mt = { }
656local add
657add = function(self, right)
658 return setmetatable({
659 value = self.value + right.value
660 }, mt)
661end
662mt.__add = add
663local a = setmetatable({
664 value = 1
665}, mt)
666local b = setmetatable({
667 value = 2
668}, {
669 __add = add
670})
671local c = setmetatable({
672 value = 3
673}, {
674 __add = mt.__add
675})
676local d = a + b + c
677print(d.value)
678local _ <close> = setmetatable({ }, {
679 __close = function()
680 return print("out of scope")
681 end
682})
683local tb = setmetatable({ }, {
684 ["value"] = 123
685})
686getmetatable(tb).__index = getmetatable(tb)
687print(tb.value)
688setmetatable(tb, {
689 __index = {
690 item = "hello"
691 }
692})
693print(tb.item)
694local item, new, close, getter
695do
696 local _obj_0 = tb
697 item, new = _obj_0[1], _obj_0.new
698 do
699 local _obj_1 = getmetatable(_obj_0)
700 close, getter = _obj_1.__close, _obj_1.__index
701 end
702end
703print(item, new, close, getter)
704do
705 local _obj_0 = func
706 if _obj_0 ~= nil then
707 _obj_0()
708 end
709end
710print((function()
711 local _obj_0 = abc
712 if _obj_0 ~= nil then
713 local _obj_1 = _obj_0["hello world"]
714 if _obj_1 ~= nil then
715 return _obj_1.xyz
716 end
717 return nil
718 end
719 return nil
720end)())
721local x
722do
723 local _obj_0 = tab
724 if _obj_0 ~= nil then
725 x = _obj_0.value
726 end
727end
728local len = (function()
729 local _obj_0 = utf8
730 if _obj_0 ~= nil then
731 return _obj_0.len
732 end
733 return nil
734end)() or (function()
735 local _obj_0 = string
736 if _obj_0 ~= nil then
737 return _obj_0.len
738 end
739 return nil
740end)() or function(o)
741 return #o
742end
743if print and (x ~= nil) then
744 print(x)
745end
746local _with_0 = io.open("test.txt", "w")
747if _with_0 ~= nil then
748 _with_0:write("hello")
749 _with_0:close()
750end
751print("hello")
752print(1, 2)
753print(1, 2, 3)
754print(render(emit(parse(extract(readFile("example.txt"), language, { }), language))))
755local a, b, c, d
756if b ~= nil then
757 a = b
758else
759 if c ~= nil then
760 a = c
761 else
762 a = d
763 end
764end
765func((function()
766 if a ~= nil then
767 return a
768 else
769 return { }
770 end
771end)())
772if a == nil then
773 a = false
774end
775local list = {
776 1,
777 2,
778 3
779}
780func({
781 1,
782 2,
783 3
784})
785local f
786f = function()
787 return {
788 1,
789 2,
790 3
791 }
792end
793local tb = {
794 name = "abc",
795 values = {
796 "a",
797 "b",
798 "c"
799 },
800 objects = {
801 {
802 name = "a",
803 value = 1,
804 func = function(self)
805 return self.value + 1
806 end,
807 tb = {
808 fieldA = 1
809 }
810 },
811 {
812 name = "b",
813 value = 2,
814 func = function(self)
815 return self.value + 2
816 end,
817 tb = { }
818 }
819 }
820}
821do
822 local insert, concat = table.insert, table.concat
823 local C, Ct, Cmt
824 do
825 local _obj_0 = require("lpeg")
826 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
827 end
828 local x, y, z
829 do
830 local _obj_0 = require('mymodule')
831 x, y, z = _obj_0.x, _obj_0.y, _obj_0.z
832 end
833 local a, b, c
834 local _obj_0 = require('module')
835 a, b, c = _obj_0.a, _obj_0.b, _obj_0.c
836end
837do
838 local module = require('module')
839 local module_x = require('module_x')
840 local d_a_s_h_e_s = require("d-a-s-h-e-s")
841 local part = require("module.part")
842end
843do
844 local PlayerModule = require("player")
845 local C, Ct, Cmt
846 do
847 local _obj_0 = require("lpeg")
848 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
849 end
850 local one, two, ch
851 local _obj_0 = require("export")
852 one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1]
853end
854do
855 local tostring <const> = tostring
856 local concat <const> = table.concat
857 print(concat({
858 "a",
859 tostring(1)
860 }))
861end
862do
863 local print <const> = print
864 local math <const> = math
865 print("hello")
866 math.random(3)
867end
868do
869 local print <const> = print
870 print(FLAG)
871 FLAG = 123
872end
873local _module_0 = { }
874local a, b, c = 1, 2, 3
875_module_0["a"], _module_0["b"], _module_0["c"] = a, b, c
876local cool = "cat"
877_module_0["cool"] = cool
878local What
879if this then
880 What = "abc"
881else
882 What = "def"
883end
884_module_0["What"] = What
885local y
886y = function()
887 local hallo = 3434
888end
889_module_0["y"] = y
890local Something
891local _class_0
892local _base_0 = {
893 umm = "cool"
894}
895if _base_0.__index == nil then
896 _base_0.__index = _base_0
897end
898_class_0 = setmetatable({
899 __init = function() end,
900 __base = _base_0,
901 __name = "Something"
902}, {
903 __index = _base_0,
904 __call = function(cls, ...)
905 local _self_0 = setmetatable({ }, _base_0)
906 cls.__init(_self_0, ...)
907 return _self_0
908 end
909})
910_base_0.__class = _class_0
911Something = _class_0
912_module_0["Something"] = Something
913return _module_0
914local _module_0 = { }
915local loadstring, tolua
916do
917 local _obj_0 = yue
918 loadstring, tolua = _obj_0.loadstring, _obj_0.to_lua
919end
920_module_0["loadstring"], _module_0["tolua"] = loadstring, tolua
921local fieldA = tb.itemA.fieldA
922if fieldA == nil then
923 fieldA = 'default'
924end
925_module_0["fieldA"] = fieldA
926return _module_0
927local _module_0 = setmetatable({ }, { })
928_module_0.itemA = tb
929getmetatable(_module_0).__index = items
930_module_0["a-b-c"] = 123
931return _module_0
932local _module_0 = { }
933local d, e, f = 3, 2, 1
934_module_0[#_module_0 + 1] = d
935_module_0[#_module_0 + 1] = e
936_module_0[#_module_0 + 1] = f
937if this then
938 _module_0[#_module_0 + 1] = 123
939else
940 _module_0[#_module_0 + 1] = 456
941end
942local _with_0 = tmp
943local j = 2000
944_module_0[#_module_0 + 1] = _with_0
945return _module_0
946local _module_0 = nil
947_module_0 = function()
948 print("hello")
949 return 123
950end
951return _module_0
411do 952do
412 local insert, concat = table.insert, table.concat 953 local insert, concat = table.insert, table.concat
413 local C, Ct, Cmt 954 local C, Ct, Cmt
@@ -590,6 +1131,57 @@ do
590 B = 2 1131 B = 2
591 local Temp = "a local value" 1132 local Temp = "a local value"
592end 1133end
1134local hello = "world"
1135local a, b, c = 1, 2, 3
1136hello = 123
1137local x = 1
1138x = x + 1
1139x = x - 1
1140x = x * 10
1141x = x / 10
1142x = x % 10
1143local s = s .. "world"
1144local arg = arg or "default value"
1145local a = 0
1146local b = 0
1147local c = 0
1148local d = 0
1149local e = 0
1150local x = f()
1151local y = x
1152local z = x
1153do
1154 local a = 1
1155 local x, y, z
1156 print("forward declare all variables as locals")
1157 x = function()
1158 return 1 + y + z
1159 end
1160 y, z = 2, 3
1161 instance = Item:new()
1162end
1163do
1164 local X = 1
1165 local B
1166 print("only forward declare upper case variables")
1167 local a = 1
1168 B = 2
1169end
1170do
1171 a = 1
1172 print("declare all variables as globals")
1173 x = function()
1174 return 1 + y + z
1175 end
1176 y, z = 2, 3
1177end
1178do
1179 X = 1
1180 print("only declare upper case variables as globals")
1181 local a = 1
1182 B = 2
1183 local Temp = "a local value"
1184end
593local thing = { 1185local thing = {
594 1, 1186 1,
595 2 1187 2
@@ -707,6 +1299,155 @@ for _index_0 = 1, #tuples do
707 local left, right = _des_0[1], _des_0[2] 1299 local left, right = _des_0[1], _des_0[2]
708 print(left, right) 1300 print(left, right)
709end 1301end
1302local thing = {
1303 1,
1304 2
1305}
1306local a, b = thing[1], thing[2]
1307print(a, b)
1308local obj = {
1309 hello = "world",
1310 day = "tuesday",
1311 length = 20
1312}
1313local hello, the_day = obj.hello, obj.day
1314print(hello, the_day)
1315local day = obj.day
1316local obj2 = {
1317 numbers = {
1318 1,
1319 2,
1320 3,
1321 4
1322 },
1323 properties = {
1324 color = "green",
1325 height = 13.5
1326 }
1327}
1328local first, second = obj2.numbers[1], obj2.numbers[2]
1329print(first, second, color)
1330local first, second, color
1331local _obj_0 = obj2
1332first, second, color = _obj_0.numbers[1], _obj_0.numbers[2], _obj_0.properties.color
1333local concat, insert
1334local _obj_0 = table
1335concat, insert = _obj_0.concat, _obj_0.insert
1336local mix, max, rand
1337local _obj_0 = math
1338mix, max, rand = _obj_0.mix, _obj_0.max, _obj_0.random
1339local name, job
1340local _obj_0 = person
1341name, job = _obj_0.name, _obj_0.job
1342if name == nil then
1343 name = "nameless"
1344end
1345if job == nil then
1346 job = "jobless"
1347end
1348local two, four
1349local _obj_0 = items
1350two, four = _obj_0[2], _obj_0[4]
1351local orders = {
1352 "first",
1353 "second",
1354 "third",
1355 "fourth",
1356 "last"
1357}
1358local first, bulk, last = orders[1], (function()
1359 local _accum_0 = { }
1360 local _len_0 = 1
1361 local _max_0 = #orders + -2 + 1
1362 for _index_0 = 2, _max_0 do
1363 local _item_0 = orders[_index_0]
1364 _accum_0[_len_0] = _item_0
1365 _len_0 = _len_0 + 1
1366 end
1367 return _accum_0
1368end)(), orders[#orders]
1369print(first)
1370print(bulk)
1371print(last)
1372local first, rest
1373do
1374 local _obj_0 = orders
1375 first, rest = _obj_0[1], (function()
1376 local _accum_0 = { }
1377 local _len_0 = 1
1378 local _max_0 = #_obj_0
1379 for _index_0 = 2, _max_0 do
1380 local _item_0 = _obj_0[_index_0]
1381 _accum_0[_len_0] = _item_0
1382 _len_0 = _len_0 + 1
1383 end
1384 return _accum_0
1385 end)()
1386end
1387local start, last
1388do
1389 local _obj_0 = orders
1390 start, last = (function()
1391 local _accum_0 = { }
1392 local _len_0 = 1
1393 local _max_0 = #_obj_0 + -2 + 1
1394 for _index_0 = 1, _max_0 do
1395 local _item_0 = _obj_0[_index_0]
1396 _accum_0[_len_0] = _item_0
1397 _len_0 = _len_0 + 1
1398 end
1399 return _accum_0
1400 end)(), _obj_0[#_obj_0]
1401end
1402local _obj_0 = orders
1403first, last = _obj_0[1], _obj_0[#_obj_0]
1404local tuples = {
1405 {
1406 "hello",
1407 "world"
1408 },
1409 {
1410 "egg",
1411 "head"
1412 }
1413}
1414for _index_0 = 1, #tuples do
1415 local _des_0 = tuples[_index_0]
1416 local left, right = _des_0[1], _des_0[2]
1417 print(left, right)
1418end
1419local user = database.find_user("moon")
1420if user then
1421 print(user.name)
1422end
1423local hello = os.getenv("hello")
1424if hello then
1425 print("You have hello", hello)
1426else
1427 local world = os.getenv("world")
1428 if world then
1429 print("you have world", world)
1430 else
1431 print("nothing :(")
1432 end
1433end
1434do
1435 local success, result = pcall(function()
1436 return "get result without problems"
1437 end)
1438 if success then
1439 print(result)
1440 end
1441end
1442print("OK")
1443repeat
1444 local byte = stream:read_one()
1445 if byte then
1446 print(byte)
1447 else
1448 break
1449 end
1450until false
710local user = database.find_user("moon") 1451local user = database.find_user("moon")
711if user then 1452if user then
712 print(user.name) 1453 print(user.name)
@@ -756,6 +1497,31 @@ end
756 local first = select(1, ...) 1497 local first = select(1, ...)
757 return print(ok, count, first) 1498 return print(ok, count, first)
758end)(fn(true)) 1499end)(fn(true))
1500local list = {
1501 1,
1502 2,
1503 3,
1504 4,
1505 5
1506}
1507local fn
1508fn = function(ok)
1509 return ok, table.unpack(list)
1510end
1511(function(_arg_0, ...)
1512 local ok = _arg_0
1513 local count = select('#', ...)
1514 local first = select(1, ...)
1515 return print(ok, count, first)
1516end)(fn(true))
1517local a = 1
1518local b = 2
1519print(a + b)
1520Rx.Observable.fromRange(1, 8):filter(function(x)
1521 return x % 2 == 0
1522end):concat(Rx.Observable.of('who do we appreciate')):map(function(value)
1523 return value .. '!'
1524end):subscribe(print)
759local a = 1 1525local a = 1
760local b = 2 1526local b = 2
761print(a + b) 1527print(a + b)
@@ -766,6 +1532,88 @@ end):concat(Rx.Observable.of('who do we appreciate')):map(function(value)
766end):subscribe(print) 1532end):subscribe(print)
767local str = strA .. strB .. strC 1533local str = strA .. strB .. strC
768func(3000, "192.168.1.1") 1534func(3000, "192.168.1.1")
1535local str = strA .. strB .. strC
1536func(3000, "192.168.1.1")
1537xpcall(function()
1538 return func(1, 2, 3)
1539end, function(err)
1540 return print(yue.traceback(err))
1541end)
1542local success, result = xpcall(function()
1543 return func(1, 2, 3)
1544end, function(err)
1545 return yue.traceback(err)
1546end)
1547xpcall(function()
1548 return func(1, 2, 3)
1549end, function(err)
1550 return print(yue.traceback(err))
1551end)
1552success, result = pcall(function()
1553 return func(1, 2, 3)
1554end)
1555pcall(function()
1556 print("trying")
1557 return func(1, 2, 3)
1558end)
1559success, result = xpcall(function()
1560 return func(1, 2, 3)
1561end, function(err)
1562 return print(yue.traceback(err))
1563end)
1564if success then
1565 print(result)
1566end
1567local a, b, c
1568do
1569 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
1570 return func()
1571 end)
1572 if _ok_0 then
1573 a, b, c = _ret_0, _ret_1, _ret_2
1574 end
1575end
1576do
1577 local _exp_0 = ((function()
1578 return (function(_arg_0, ...)
1579 local _ok_0 = _arg_0
1580 if _ok_0 then
1581 return ...
1582 end
1583 end)(pcall(function()
1584 return func()
1585 end))
1586 end)())
1587 if _exp_0 ~= nil then
1588 a = _exp_0
1589 else
1590 a = "default"
1591 end
1592end
1593f((function()
1594 return (function(_arg_0, ...)
1595 local _ok_0 = _arg_0
1596 if _ok_0 then
1597 return ...
1598 end
1599 end)(pcall(function()
1600 return func()
1601 end))
1602end)())
1603f((function()
1604 return (function(_arg_0, ...)
1605 local _ok_0 = _arg_0
1606 if _ok_0 then
1607 return ...
1608 end
1609 end)(xpcall(function()
1610 print(123)
1611 return func()
1612 end, function(e)
1613 print(e)
1614 return e
1615 end))
1616end)())
769xpcall(function() 1617xpcall(function()
770 return func(1, 2, 3) 1618 return func(1, 2, 3)
771end, function(err) 1619end, function(err)
@@ -856,6 +1704,28 @@ local a, b, c, d
856local _obj_0 = tb 1704local _obj_0 = tb
857a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] 1705a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
858Constant = 123 1706Constant = 123
1707local a <const> = 123
1708local _ <close> = setmetatable({ }, {
1709 __close = function()
1710 return print("Out of scope.")
1711 end
1712})
1713local a, b, c, d
1714local _obj_0 = tb
1715a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
1716Constant = 123
1717local some_string = "Here is a string\n that has a line break in it."
1718print("I am " .. tostring(math.random() * 100) .. "% sure.")
1719local integer = 1000000
1720local hex = 0xEFBBBF
1721local binary = 19
1722local str = "key: value\nlist:\n - item1\n - " .. tostring(expr)
1723local fn
1724fn = function()
1725 local str = "foo:\n bar: baz"
1726 return str
1727end
1728local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
859local some_string = "Here is a string\n that has a line break in it." 1729local some_string = "Here is a string\n that has a line break in it."
860print("I am " .. tostring(math.random() * 100) .. "% sure.") 1730print("I am " .. tostring(math.random() * 100) .. "% sure.")
861local integer = 1000000 1731local integer = 1000000
@@ -1052,8 +1922,192 @@ process = function(...)
1052 return sum 1922 return sum
1053end 1923end
1054process(1, nil, 3, nil, 5) 1924process(1, nil, 3, nil, 5)
1055f(function() 1925local my_function
1056 return print("hello") 1926my_function = function() end
1927my_function()
1928local func_a
1929func_a = function()
1930 return print("hello world")
1931end
1932local func_b
1933func_b = function()
1934 local value = 100
1935 return print("The value:", value)
1936end
1937func_a()
1938func_b()
1939local sum
1940sum = function(x, y)
1941 return print("sum", x + y)
1942end
1943sum(10, 20)
1944print(sum(10, 20))
1945a(b(c("a", "b", "c")))
1946print("x:", sum(10, 20), "y:", sum(30, 40))
1947local sum
1948sum = function(x, y)
1949 return x + y
1950end
1951print("The sum is ", sum(10, 20))
1952local sum
1953sum = function(x, y)
1954 return x + y
1955end
1956local mystery
1957mystery = function(x, y)
1958 return x + y, x - y
1959end
1960local a, b = mystery(10, 20)
1961local func
1962func = function(self, num)
1963 return self.value + num
1964end
1965local my_function
1966my_function = function(name, height)
1967 if name == nil then
1968 name = "something"
1969 end
1970 if height == nil then
1971 height = 100
1972 end
1973 print("Hello I am", name)
1974 return print("My height is", height)
1975end
1976local some_args
1977some_args = function(x, y)
1978 if x == nil then
1979 x = 100
1980 end
1981 if y == nil then
1982 y = x + 1000
1983 end
1984 return print(x + y)
1985end
1986local a = x - 10
1987local b = x - 10
1988local c = x(-y)
1989local d = x - z
1990local x = func("hello") + 100
1991local y = func("hello" + 100)
1992my_func(5, 4, 3, 8, 9, 10)
1993cool_func(1, 2, 3, 4, 5, 6, 7, 8)
1994my_func(5, 6, 7, 6, another_func(6, 7, 8, 9, 1, 2), 5, 4)
1995local x = {
1996 1,
1997 2,
1998 3,
1999 4,
2000 a_func(4, 5, 5, 6),
2001 8,
2002 9,
2003 10
2004}
2005local y = {
2006 my_func(1, 2, 3, 4, 5),
2007 5,
2008 6,
2009 7
2010}
2011if func(1, 2, 3, "hello", "world") then
2012 print("hello")
2013 print("I am inside if")
2014end
2015if func(1, 2, 3, "hello", "world") then
2016 print("hello")
2017 print("I am inside if")
2018end
2019local f1
2020f1 = function(_arg_0)
2021 local a, b, c
2022 a, b, c = _arg_0.a, _arg_0.b, _arg_0.c
2023 return print(a, b, c)
2024end
2025f1({
2026 a = 1,
2027 b = "2",
2028 c = { }
2029})
2030local f2
2031f2 = function(_arg_0, c)
2032 local a1, b
2033 a1, b = _arg_0.a, _arg_0.b
2034 if a1 == nil then
2035 a1 = 123
2036 end
2037 if b == nil then
2038 b = 'abc'
2039 end
2040 if c == nil then
2041 c = { }
2042 end
2043end
2044print(a1, b, c)
2045local arg1 = {
2046 a = 0
2047}
2048f2(arg1, arg2)
2049local findFirstEven
2050findFirstEven = function(list)
2051 for _index_0 = 1, #list do
2052 local item = list[_index_0]
2053 if type(item) == "table" then
2054 for _index_1 = 1, #item do
2055 local sub = item[_index_1]
2056 if sub % 2 == 0 then
2057 return sub
2058 end
2059 end
2060 end
2061 end
2062 return nil
2063end
2064local findFirstEven
2065findFirstEven = function(list)
2066 for _index_0 = 1, #list do
2067 local item = list[_index_0]
2068 if type(item) == "table" then
2069 for _index_1 = 1, #item do
2070 local sub = item[_index_1]
2071 if sub % 2 == 0 then
2072 return sub
2073 end
2074 end
2075 end
2076 end
2077 return nil
2078end
2079local f
2080f = function(...)
2081 local t = {
2082 n = select("#", ...),
2083 ...
2084 }
2085 print("argument count:", t.n)
2086 print("table length:", #t)
2087 for i = 1, t.n do
2088 print(t[i])
2089 end
2090end
2091f(1, 2, 3)
2092f("a", "b", "c", "d")
2093f()
2094local process
2095process = function(...)
2096 local args = {
2097 n = select("#", ...),
2098 ...
2099 }
2100 local sum = 0
2101 for i = 1, args.n do
2102 if args[i] ~= nil and type(args[i]) == "number" then
2103 sum = sum + args[i]
2104 end
2105 end
2106 return sum
2107end
2108process(1, nil, 3, nil, 5)
2109f(function(x)
2110 return print("hello" .. x)
1057end) 2111end)
1058f(function(self) 2112f(function(self)
1059 return print(self.value) 2113 return print(self.value)
@@ -1075,6 +2129,97 @@ do
1075 end) 2129 end)
1076end 2130end
1077print(result, msg) 2131print(result, msg)
2132f(function(x)
2133 return print("hello" .. x)
2134end)
2135f(function(self)
2136 return print(self.value)
2137end)
2138map(function(x)
2139 return x * 2
2140end, {
2141 1,
2142 2,
2143 3
2144})
2145local result, msg
2146do
2147 result, msg = readAsync("filename.txt", function(data)
2148 print(data)
2149 return processAsync(data, function(info)
2150 return check(info)
2151 end)
2152 end)
2153end
2154print(result, msg)
2155local some_values = {
2156 1,
2157 2,
2158 3,
2159 4
2160}
2161local some_values = {
2162 name = "Bill",
2163 age = 200,
2164 ["favorite food"] = "rice"
2165}
2166local profile = {
2167 height = "4 feet",
2168 shoe_size = 13,
2169 favorite_foods = {
2170 "ice cream",
2171 "donuts"
2172 }
2173}
2174local values = {
2175 1,
2176 2,
2177 3,
2178 4,
2179 5,
2180 6,
2181 7,
2182 8,
2183 name = "superman",
2184 occupation = "crime fighting"
2185}
2186my_function({
2187 dance = "Tango",
2188 partner = "none"
2189})
2190local y = {
2191 type = "dog",
2192 legs = 4,
2193 tails = 1
2194}
2195local tbl = {
2196 ["do"] = "something",
2197 ["end"] = "hunger"
2198}
2199local hair = "golden"
2200local height = 200
2201local person = {
2202 hair = hair,
2203 height = height,
2204 shoe_size = 40
2205}
2206print_table({
2207 hair = hair,
2208 height = height
2209})
2210local t = {
2211 [1 + 2] = "hello",
2212 ["hello world"] = true
2213}
2214local some_values = {
2215 1,
2216 2,
2217 3,
2218 4
2219}
2220local list_with_one_element = {
2221 1
2222}
1078local some_values = { 2223local some_values = {
1079 1, 2224 1,
1080 2, 2225 2,
@@ -1341,15 +2486,250 @@ for _index_0 = _min_0, 1, -1 do
1341end 2486end
1342reverse_slice = _accum_0 2487reverse_slice = _accum_0
1343local sub_list 2488local sub_list
2489do
2490 local _accum_0 = { }
2491 local _len_0 = 1
2492 local _list_0 = items
2493 for _index_0 = 2, 4 do
2494 local _item_0 = _list_0[_index_0]
2495 _accum_0[_len_0] = _item_0
2496 _len_0 = _len_0 + 1
2497 end
2498 sub_list = _accum_0
2499end
2500local last_four_items
1344local _accum_0 = { } 2501local _accum_0 = { }
1345local _len_0 = 1 2502local _len_0 = 1
1346local _list_0 = items 2503local _list_0 = items
1347for _index_0 = 2, 4 do 2504local _min_0 = #_list_0 + -4 + 1
2505local _max_0 = #_list_0 + -1 + 1
2506for _index_0 = _min_0, _max_0 do
1348 local _item_0 = _list_0[_index_0] 2507 local _item_0 = _list_0[_index_0]
1349 _accum_0[_len_0] = _item_0 2508 _accum_0[_len_0] = _item_0
1350 _len_0 = _len_0 + 1 2509 _len_0 = _len_0 + 1
1351end 2510end
1352sub_list = _accum_0 2511last_four_items = _accum_0
2512local items = {
2513 1,
2514 2,
2515 3,
2516 4
2517}
2518local doubled
2519local _accum_0 = { }
2520local _len_0 = 1
2521for i, item in ipairs(items) do
2522 _accum_0[_len_0] = item * 2
2523 _len_0 = _len_0 + 1
2524end
2525doubled = _accum_0
2526local slice
2527local _accum_0 = { }
2528local _len_0 = 1
2529for i, item in ipairs(items) do
2530 if i > 1 and i < 3 then
2531 _accum_0[_len_0] = item
2532 _len_0 = _len_0 + 1
2533 end
2534end
2535slice = _accum_0
2536local doubled
2537local _accum_0 = { }
2538local _len_0 = 1
2539local _list_0 = items
2540for _index_0 = 1, #_list_0 do
2541 local item = _list_0[_index_0]
2542 _accum_0[_len_0] = item * 2
2543 _len_0 = _len_0 + 1
2544end
2545doubled = _accum_0
2546local data = {
2547 a = {
2548 1,
2549 2,
2550 3
2551 },
2552 b = {
2553 4,
2554 5,
2555 6
2556 }
2557}
2558local flat
2559local _accum_0 = { }
2560for k, v in pairs(data) do
2561 local _len_0 = #_accum_0 + 1
2562 for _index_0 = 1, #v do
2563 local _elm_0 = v[_index_0]
2564 _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1
2565 end
2566end
2567flat = _accum_0
2568local x_coords = {
2569 4,
2570 5,
2571 6,
2572 7
2573}
2574local y_coords = {
2575 9,
2576 2,
2577 3
2578}
2579local points
2580local _accum_0 = { }
2581local _len_0 = 1
2582for _index_0 = 1, #x_coords do
2583 local x = x_coords[_index_0]
2584 for _index_1 = 1, #y_coords do
2585 local y = y_coords[_index_1]
2586 _accum_0[_len_0] = {
2587 x,
2588 y
2589 }
2590 _len_0 = _len_0 + 1
2591 end
2592end
2593points = _accum_0
2594local evens
2595local _accum_0 = { }
2596local _len_0 = 1
2597for i = 1, 100 do
2598 if i % 2 == 0 then
2599 _accum_0[_len_0] = i
2600 _len_0 = _len_0 + 1
2601 end
2602end
2603evens = _accum_0
2604local thing = {
2605 color = "red",
2606 name = "fast",
2607 width = 123
2608}
2609local thing_copy
2610local _tbl_0 = { }
2611for k, v in pairs(thing) do
2612 _tbl_0[k] = v
2613end
2614thing_copy = _tbl_0
2615local no_color
2616local _tbl_0 = { }
2617for k, v in pairs(thing) do
2618 if k ~= "color" then
2619 _tbl_0[k] = v
2620 end
2621end
2622no_color = _tbl_0
2623local numbers = {
2624 1,
2625 2,
2626 3,
2627 4
2628}
2629local sqrts
2630local _tbl_0 = { }
2631for _index_0 = 1, #numbers do
2632 local i = numbers[_index_0]
2633 _tbl_0[i] = math.sqrt(i)
2634end
2635sqrts = _tbl_0
2636local tuples = {
2637 {
2638 "hello",
2639 "world"
2640 },
2641 {
2642 "foo",
2643 "bar"
2644 }
2645}
2646local tbl
2647local _tbl_0 = { }
2648for _index_0 = 1, #tuples do
2649 local tuple = tuples[_index_0]
2650 local _key_0, _val_0 = unpack(tuple)
2651 _tbl_0[_key_0] = _val_0
2652end
2653tbl = _tbl_0
2654local slice
2655local _accum_0 = { }
2656local _len_0 = 1
2657local _list_0 = items
2658for _index_0 = 1, 5 do
2659 local item = _list_0[_index_0]
2660 _accum_0[_len_0] = item
2661 _len_0 = _len_0 + 1
2662end
2663slice = _accum_0
2664local slice
2665local _accum_0 = { }
2666local _len_0 = 1
2667local _list_0 = items
2668local _max_0 = #_list_0
2669for _index_0 = 2, _max_0 do
2670 local item = _list_0[_index_0]
2671 _accum_0[_len_0] = item
2672 _len_0 = _len_0 + 1
2673end
2674slice = _accum_0
2675local slice
2676local _accum_0 = { }
2677local _len_0 = 1
2678local _list_0 = items
2679local _max_0 = #_list_0
2680for _index_0 = 1, _max_0, 2 do
2681 local item = _list_0[_index_0]
2682 _accum_0[_len_0] = item
2683 _len_0 = _len_0 + 1
2684end
2685slice = _accum_0
2686local slice
2687local _accum_0 = { }
2688local _len_0 = 1
2689local _list_0 = items
2690local _min_0 = #_list_0 + -4 + 1
2691local _max_0 = #_list_0 + -1 + 1
2692for _index_0 = _min_0, _max_0 do
2693 local item = _list_0[_index_0]
2694 _accum_0[_len_0] = item
2695 _len_0 = _len_0 + 1
2696end
2697slice = _accum_0
2698local reverse_slice
2699local _accum_0 = { }
2700local _len_0 = 1
2701local _list_0 = items
2702local _min_0 = #_list_0 + -1 + 1
2703for _index_0 = _min_0, 1, -1 do
2704 local item = _list_0[_index_0]
2705 _accum_0[_len_0] = item
2706 _len_0 = _len_0 + 1
2707end
2708reverse_slice = _accum_0
2709local sub_list
2710do
2711 local _accum_0 = { }
2712 local _len_0 = 1
2713 local _list_0 = items
2714 for _index_0 = 2, 4 do
2715 local _item_0 = _list_0[_index_0]
2716 _accum_0[_len_0] = _item_0
2717 _len_0 = _len_0 + 1
2718 end
2719 sub_list = _accum_0
2720end
2721local last_four_items
2722local _accum_0 = { }
2723local _len_0 = 1
2724local _list_0 = items
2725local _min_0 = #_list_0 + -4 + 1
2726local _max_0 = #_list_0 + -1 + 1
2727for _index_0 = _min_0, _max_0 do
2728 local _item_0 = _list_0[_index_0]
2729 _accum_0[_len_0] = _item_0
2730 _len_0 = _len_0 + 1
2731end
2732last_four_items = _accum_0
1353for i = 10, 20 do 2733for i = 10, 20 do
1354 print(i) 2734 print(i)
1355end 2735end
@@ -1414,6 +2794,86 @@ func_b = function()
1414end 2794end
1415print(func_a()) 2795print(func_a())
1416print(func_b()) 2796print(func_b())
2797for i = 10, 20 do
2798 print(i)
2799end
2800for k = 1, 15, 2 do
2801 print(k)
2802end
2803for key, value in pairs(object) do
2804 print(key, value)
2805end
2806local _list_0 = items
2807for _index_0 = 2, 4 do
2808 local item = _list_0[_index_0]
2809 print(item)
2810end
2811local _list_0 = items
2812for _index_0 = 1, #_list_0 do
2813 local item = _list_0[_index_0]
2814 print(item)
2815end
2816for j = 1, 10, 3 do
2817 print(j)
2818end
2819local doubled_evens
2820local _accum_0 = { }
2821local _len_0 = 1
2822for i = 1, 20 do
2823 if i % 2 == 0 then
2824 _accum_0[_len_0] = i * 2
2825 _len_0 = _len_0 + 1
2826 else
2827 _accum_0[_len_0] = i
2828 _len_0 = _len_0 + 1
2829 end
2830end
2831doubled_evens = _accum_0
2832local first_large
2833local _accum_0
2834local _list_0 = numbers
2835for _index_0 = 1, #_list_0 do
2836 local n = _list_0[_index_0]
2837 if n > 10 then
2838 _accum_0 = n
2839 break
2840 end
2841end
2842first_large = _accum_0
2843local func_a
2844func_a = function()
2845 for i = 1, 10 do
2846 print(i)
2847 end
2848end
2849local func_b
2850func_b = function()
2851 local _accum_0 = { }
2852 local _len_0 = 1
2853 for i = 1, 10 do
2854 _accum_0[_len_0] = i
2855 _len_0 = _len_0 + 1
2856 end
2857 return _accum_0
2858end
2859print(func_a())
2860print(func_b())
2861local i = 10
2862while i > 0 do
2863 print(i)
2864 i = i - 1
2865end
2866while running == true do
2867 my_function()
2868end
2869local i = 10
2870while not (i == 0) do
2871 print(i)
2872 i = i - 1
2873end
2874while not (running == false) do
2875 my_function()
2876end
1417local i = 10 2877local i = 10
1418repeat 2878repeat
1419 print(i) 2879 print(i)
@@ -1435,6 +2895,41 @@ end
1435while not (running == false) do 2895while not (running == false) do
1436 my_function() 2896 my_function()
1437end 2897end
2898local i = 10
2899repeat
2900 print(i)
2901 i = i - 1
2902until i == 0
2903local i = 0
2904while i < 10 do
2905 i = i + 1
2906 if i % 2 == 0 then
2907 goto _continue_0
2908 end
2909 print(i)
2910 ::_continue_0::
2911end
2912local my_numbers = {
2913 1,
2914 2,
2915 3,
2916 4,
2917 5,
2918 6
2919}
2920local odds
2921local _accum_0 = { }
2922local _len_0 = 1
2923for _index_0 = 1, #my_numbers do
2924 local x = my_numbers[_index_0]
2925 if x % 2 == 1 then
2926 goto _continue_0
2927 end
2928 _accum_0[_len_0] = x
2929 _len_0 = _len_0 + 1
2930 ::_continue_0::
2931end
2932odds = _accum_0
1438local i = 0 2933local i = 0
1439while i < 10 do 2934while i < 10 do
1440 i = i + 1 2935 i = i + 1
@@ -1524,6 +3019,79 @@ end
1524if not (math.random() > 0.1) then 3019if not (math.random() > 0.1) then
1525 print("You're lucky!") 3020 print("You're lucky!")
1526end 3021end
3022local have_coins = false
3023if have_coins then
3024 print("Got coins")
3025else
3026 print("No coins")
3027end
3028local have_coins = false
3029if have_coins then
3030 print("Got coins")
3031else
3032 print("No coins")
3033end
3034local have_coins = false
3035print((function()
3036 if have_coins then
3037 return "Got coins"
3038 else
3039 return "No coins"
3040 end
3041end)())
3042local is_tall
3043is_tall = function(name)
3044 if name == "Rob" then
3045 return true
3046 else
3047 return false
3048 end
3049end
3050local message
3051if is_tall("Rob") then
3052 message = "I am very tall"
3053else
3054 message = "I am not so tall"
3055end
3056print(message)
3057if not (os.date("%A") == "Monday") then
3058 print("it is not Monday!")
3059end
3060if not (math.random() > 0.1) then
3061 print("You're lucky!")
3062end
3063local a = 5
3064if (1 == a or 3 == a or 5 == a or 7 == a) then
3065 print("checking equality with discrete values")
3066end
3067if (function()
3068 local _check_0 = list
3069 for _index_0 = 1, #_check_0 do
3070 if _check_0[_index_0] == a then
3071 return true
3072 end
3073 end
3074 return false
3075end)() then
3076 print("checking if `a` is in a list")
3077end
3078if not (math.random() > 0.1) then
3079 print("You're lucky!")
3080end
3081if name == "Rob" then
3082 print("hello world")
3083end
3084local _list_0 = items
3085for _index_0 = 1, #_list_0 do
3086 local item = _list_0[_index_0]
3087 print("item: ", item)
3088end
3089while game:isRunning() do
3090 game:update()
3091end
3092while not reader:eof() do
3093 reader:parse_line()
3094end
1527if name == "Rob" then 3095if name == "Rob" then
1528 print("hello world") 3096 print("hello world")
1529end 3097end
@@ -1830,6 +3398,298 @@ if _tab_0 then
1830 print("Action:", action) 3398 print("Action:", action)
1831 end 3399 end
1832end 3400end
3401local name = "Dan"
3402if "Robert" == name then
3403 print("You are Robert")
3404elseif "Dan" == name or "Daniel" == name then
3405 print("Your name, it's Dan")
3406else
3407 print("I don't know about you with name " .. tostring(name))
3408end
3409local b = 1
3410local next_number
3411if 1 == b then
3412 next_number = 2
3413elseif 2 == b then
3414 next_number = 3
3415else
3416 next_number = error("can't count that high!")
3417end
3418local msg
3419local _exp_0 = math.random(1, 5)
3420if 1 == _exp_0 then
3421 msg = "you are lucky"
3422elseif 2 == _exp_0 then
3423 msg = "you are almost lucky"
3424else
3425 msg = "not so lucky"
3426end
3427do
3428 local _exp_0 = math.random(1, 5)
3429 if 1 == _exp_0 then
3430 print("you are lucky")
3431 else
3432 print("not so lucky")
3433 end
3434end
3435local _exp_0 = math.random(1, 5)
3436if 1 == _exp_0 then
3437 print("you are lucky")
3438else
3439 print("not so lucky")
3440end
3441local items = {
3442 {
3443 x = 100,
3444 y = 200
3445 },
3446 {
3447 width = 300,
3448 height = 400
3449 }
3450}
3451for _index_0 = 1, #items do
3452 local item = items[_index_0]
3453 local _type_0 = type(item)
3454 local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3455 local _match_0 = false
3456 if _tab_0 then
3457 local x = item.x
3458 local y = item.y
3459 if x ~= nil and y ~= nil then
3460 _match_0 = true
3461 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
3462 end
3463 end
3464 if not _match_0 then
3465 if _tab_0 then
3466 local width = item.width
3467 local height = item.height
3468 if width ~= nil and height ~= nil then
3469 print("size " .. tostring(width) .. ", " .. tostring(height))
3470 end
3471 end
3472 end
3473end
3474local item = { }
3475local x, y = item.pos.x, item.pos.y
3476if x == nil then
3477 x = 50
3478end
3479if y == nil then
3480 y = 200
3481end
3482local _type_0 = type(item)
3483local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3484if _tab_0 then
3485 do
3486 local _obj_0 = item.pos
3487 local _type_1 = type(_obj_0)
3488 if "table" == _type_1 or "userdata" == _type_1 then
3489 x = _obj_0.x
3490 end
3491 end
3492 do
3493 local _obj_0 = item.pos
3494 local _type_1 = type(_obj_0)
3495 if "table" == _type_1 or "userdata" == _type_1 then
3496 y = _obj_0.y
3497 end
3498 end
3499 if x == nil then
3500 x = 50
3501 end
3502 if y == nil then
3503 y = 200
3504 end
3505 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
3506end
3507local _exp_0 = tb
3508local _type_0 = type(_exp_0)
3509local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3510local _match_0 = false
3511if _tab_0 then
3512 if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then
3513 _match_0 = true
3514 print("1, 2, 3")
3515 end
3516end
3517if not _match_0 then
3518 local _match_1 = false
3519 if _tab_0 then
3520 local b = _exp_0[2]
3521 if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then
3522 _match_1 = true
3523 print("1, " .. tostring(b) .. ", 3")
3524 end
3525 end
3526 if not _match_1 then
3527 if _tab_0 then
3528 local b = _exp_0[3]
3529 if b == nil then
3530 b = 3
3531 end
3532 if 1 == _exp_0[1] and 2 == _exp_0[2] then
3533 print("1, 2, " .. tostring(b))
3534 end
3535 end
3536 end
3537end
3538local _exp_0 = tb
3539local _type_0 = type(_exp_0)
3540local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3541local _match_0 = false
3542if _tab_0 then
3543 local result = _exp_0.result
3544 if true == _exp_0.success and result ~= nil then
3545 _match_0 = true
3546 print("success", result)
3547 end
3548end
3549if not _match_0 then
3550 local _match_1 = false
3551 if _tab_0 then
3552 if false == _exp_0.success then
3553 _match_1 = true
3554 print("failed", result)
3555 end
3556 end
3557 if not _match_1 then
3558 print("invalid")
3559 end
3560end
3561local _exp_0 = tb
3562local _type_0 = type(_exp_0)
3563local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3564local _match_0 = false
3565if _tab_0 then
3566 local content
3567 do
3568 local _obj_0 = _exp_0.data
3569 local _type_1 = type(_obj_0)
3570 if "table" == _type_1 or "userdata" == _type_1 then
3571 content = _obj_0.content
3572 end
3573 end
3574 local _val_0
3575 do
3576 local _obj_0 = _exp_0.data
3577 if _obj_0 ~= nil then
3578 _val_0 = _obj_0.type
3579 end
3580 end
3581 if "success" == _val_0 and content ~= nil then
3582 _match_0 = true
3583 print("success", content)
3584 end
3585end
3586if not _match_0 then
3587 local _match_1 = false
3588 if _tab_0 then
3589 local content
3590 do
3591 local _obj_0 = _exp_0.data
3592 local _type_1 = type(_obj_0)
3593 if "table" == _type_1 or "userdata" == _type_1 then
3594 content = _obj_0.content
3595 end
3596 end
3597 local _val_0
3598 do
3599 local _obj_0 = _exp_0.data
3600 if _obj_0 ~= nil then
3601 _val_0 = _obj_0.type
3602 end
3603 end
3604 if "error" == _val_0 and content ~= nil then
3605 _match_1 = true
3606 print("failed", content)
3607 end
3608 end
3609 if not _match_1 then
3610 print("invalid")
3611 end
3612end
3613local _exp_0 = tb
3614local _type_0 = type(_exp_0)
3615local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3616if _tab_0 then
3617 local fourth = _exp_0[4]
3618 local _val_0
3619 do
3620 local _obj_0 = _exp_0[1]
3621 if _obj_0 ~= nil then
3622 _val_0 = _obj_0.a
3623 end
3624 end
3625 local _val_1
3626 do
3627 local _obj_0 = _exp_0[1]
3628 if _obj_0 ~= nil then
3629 _val_1 = _obj_0.b
3630 end
3631 end
3632 local _val_2
3633 do
3634 local _obj_0 = _exp_0[2]
3635 if _obj_0 ~= nil then
3636 _val_2 = _obj_0.a
3637 end
3638 end
3639 local _val_3
3640 do
3641 local _obj_0 = _exp_0[2]
3642 if _obj_0 ~= nil then
3643 _val_3 = _obj_0.b
3644 end
3645 end
3646 local _val_4
3647 do
3648 local _obj_0 = _exp_0[3]
3649 if _obj_0 ~= nil then
3650 _val_4 = _obj_0.a
3651 end
3652 end
3653 local _val_5
3654 do
3655 local _obj_0 = _exp_0[3]
3656 if _obj_0 ~= nil then
3657 _val_5 = _obj_0.b
3658 end
3659 end
3660 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
3661 print("matched", fourth)
3662 end
3663end
3664local segments = {
3665 "admin",
3666 "users",
3667 "logs",
3668 "view"
3669}
3670local _type_0 = type(segments)
3671local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3672if _tab_0 then
3673 local groups
3674 do
3675 local _accum_0 = { }
3676 local _len_0 = 1
3677 local _max_0 = #segments + -3 + 1
3678 for _index_0 = 1, _max_0 do
3679 local _item_0 = segments[_index_0]
3680 _accum_0[_len_0] = _item_0
3681 _len_0 = _len_0 + 1
3682 end
3683 groups = _accum_0
3684 end
3685 local resource = segments[#segments - 1]
3686 local action = segments[#segments]
3687 if resource ~= nil and action ~= nil then
3688 print("Group:", groups)
3689 print("Resource:", resource)
3690 print("Action:", action)
3691 end
3692end
1833local Inventory 3693local Inventory
1834local _class_0 3694local _class_0
1835local _base_0 = { 3695local _base_0 = {
@@ -2450,1946 +4310,6 @@ end
2450local y = Y() 4310local y = Y()
2451y:func() 4311y:func()
2452assert(y.__class.__parent ~= X) 4312assert(y.__class.__parent ~= X)
2453local _with_0 = Person()
2454_with_0.name = "Oswald"
2455_with_0:add_relative(my_dad)
2456_with_0:save()
2457print(_with_0.name)
2458local file
2459local _with_0 = File("favorite_foods.txt")
2460_with_0:set_encoding("utf8")
2461file = _with_0
2462local create_person
2463create_person = function(name, relatives)
2464 local _with_0 = Person()
2465 _with_0.name = name
2466 for _index_0 = 1, #relatives do
2467 local relative = relatives[_index_0]
2468 _with_0:add_relative(relative)
2469 end
2470 return _with_0
2471end
2472local me = create_person("Leaf", {
2473 dad,
2474 mother,
2475 sister
2476})
2477local str = "Hello"
2478print("original:", str)
2479print("upper:", str:upper())
2480local _with_0 = tb
2481_with_0[1] = 1
2482print(_with_0[2])
2483do
2484 local _with_1 = _with_0[abc]
2485 _with_1[3] = _with_1[2]:func()
2486 _with_1["key-name"] = value
2487end
2488_with_0[#_with_0 + 1] = "abc"
2489local _with_0 = obj
2490if _with_0 ~= nil then
2491 print(obj.name)
2492end
2493do
2494 local var = "hello"
2495 print(var)
2496end
2497print(var)
2498local counter
2499do
2500 local i = 0
2501 counter = function()
2502 i = i + 1
2503 return i
2504 end
2505end
2506print(counter())
2507print(counter())
2508local tbl = {
2509 key = (function()
2510 print("assigning key!")
2511 return 1234
2512 end)()
2513}
2514local my_object = {
2515 value = 1000,
2516 write = function(self)
2517 return print("the value:", self.value)
2518 end
2519}
2520local run_callback
2521run_callback = function(func)
2522 print("running callback...")
2523 return func()
2524end
2525run_callback(my_object.write)
2526run_callback((function()
2527 local _base_0 = my_object
2528 local _fn_0 = _base_0.write
2529 return _fn_0 and function(...)
2530 return _fn_0(_base_0, ...)
2531 end
2532end)())
2533local i = 100
2534local my_func
2535my_func = function()
2536 i = 10
2537 while i > 0 do
2538 print(i)
2539 i = i - 1
2540 end
2541end
2542my_func()
2543print(i)
2544local i = 100
2545local my_func
2546my_func = function()
2547 local i = "hello"
2548end
2549my_func()
2550print(i)
2551local tmp = 1213
2552local i, k = 100, 50
2553local my_func
2554my_func = function(add)
2555 local tmp = tmp + add
2556 i = i + tmp
2557 k = k + tmp
2558end
2559my_func(22)
2560print(i, k)
2561local _module_0 = { }
2562local p, to_lua
2563do
2564 local _obj_0 = require("yue")
2565 p, to_lua = _obj_0.p, _obj_0.to_lua
2566end
2567local inventory = {
2568 equipment = {
2569 "sword",
2570 "shield"
2571 },
2572 items = {
2573 {
2574 name = "potion",
2575 count = 10
2576 },
2577 {
2578 name = "bread",
2579 count = 3
2580 }
2581 }
2582}
2583local map
2584map = function(arr, action)
2585 local _accum_0 = { }
2586 local _len_0 = 1
2587 for _index_0 = 1, #arr do
2588 local item = arr[_index_0]
2589 _accum_0[_len_0] = action(item)
2590 _len_0 = _len_0 + 1
2591 end
2592 return _accum_0
2593end
2594local filter
2595filter = function(arr, cond)
2596 local _accum_0 = { }
2597 local _len_0 = 1
2598 for _index_0 = 1, #arr do
2599 local item = arr[_index_0]
2600 if cond(item) then
2601 _accum_0[_len_0] = item
2602 _len_0 = _len_0 + 1
2603 end
2604 end
2605 return _accum_0
2606end
2607local reduce
2608reduce = function(arr, init, action)
2609 for _index_0 = 1, #arr do
2610 local item = arr[_index_0]
2611 init = action(init, item)
2612 end
2613 return init
2614end
2615print(reduce(filter(map({
2616 1,
2617 2,
2618 3
2619}, function(x)
2620 return x * 2
2621end), function(x)
2622 return x > 4
2623end), 0, function(a, b)
2624 return a + b
2625end))
2626local apple = setmetatable({
2627 size = 15,
2628}, {
2629 __index = {
2630 color = 0x00ffff
2631 }
2632})
2633if (getmetatable(apple) ~= nil) then
2634 p(apple.size, apple.color, getmetatable(apple).__index)
2635end
2636local _u1f31b = "月之脚本"
2637_module_0["🌛"] = _u1f31b
2638return _module_0
2639local area = 6.2831853071796 * 5
2640print('hello world')
2641do
2642 assert(item ~= nil)
2643end
2644local value = item
2645if (f1() and f2() and f3()) then
2646 print("OK")
2647end
2648do
2649 local funcA
2650 funcA = function() end
2651end
2652local funcA
2653funcA = function()
2654 return "fail to assign to the Yue macro defined variable"
2655end
2656do
2657local function funcB() end
2658end
2659local funcB
2660funcB = function()
2661 return "fail to assign to the Lua macro defined variable"
2662end
2663do
2664-- raw Lua codes insertion
2665if cond then
2666 print("output")
2667end
2668end
2669print("yuescript")
2670print(2)
2671print("Valid enum type:", "Static")
2672do
2673 print(123, "hello")
2674end
2675do
2676 print(123, "hello")
2677end
2678if tb ~= nil then
2679 tb:func()
2680end
2681if tb ~= nil then
2682 tb:func()
2683end
2684print(1 < 2 and 2 <= 2 and 2 < 3 and 3 == 3 and 3 > 2 and 2 >= 1 and 1 == 1 and 1 < 3 and 3 ~= 5)
2685local a = 5
2686print(1 <= a and a <= 10)
2687local v
2688v = function(x)
2689 print(x)
2690 return x
2691end
2692print((function()
2693 local _cond_0 = v(2)
2694 if not (v(1) < _cond_0) then
2695 return false
2696 else
2697 return _cond_0 <= v(3)
2698 end
2699end)())
2700print((function()
2701 local _cond_0 = v(2)
2702 if not (v(1) > _cond_0) then
2703 return false
2704 else
2705 return _cond_0 <= v(3)
2706 end
2707end)())
2708local tab = { }
2709tab[#tab + 1] = "Value"
2710local tbA = {
2711 1,
2712 2,
2713 3
2714}
2715local tbB = {
2716 4,
2717 5,
2718 6
2719}
2720local _len_0 = #tbA + 1
2721for _index_0 = 1, #tbB do
2722 local _elm_0 = tbB[_index_0]
2723 tbA[_len_0], _len_0 = _elm_0, _len_0 + 1
2724end
2725local parts = {
2726 "shoulders",
2727 "knees"
2728}
2729local lyrics
2730do
2731 local _tab_0 = {
2732 "head"
2733 }
2734 local _idx_0 = 1
2735 for _key_0, _value_0 in pairs(parts) do
2736 if _idx_0 == _key_0 then
2737 _tab_0[#_tab_0 + 1] = _value_0
2738 _idx_0 = _idx_0 + 1
2739 else
2740 _tab_0[_key_0] = _value_0
2741 end
2742 end
2743 _tab_0[#_tab_0 + 1] = "and"
2744 _tab_0[#_tab_0 + 1] = "toes"
2745 lyrics = _tab_0
2746end
2747local copy
2748do
2749 local _tab_0 = { }
2750 local _idx_0 = 1
2751 for _key_0, _value_0 in pairs(other) do
2752 if _idx_0 == _key_0 then
2753 _tab_0[#_tab_0 + 1] = _value_0
2754 _idx_0 = _idx_0 + 1
2755 else
2756 _tab_0[_key_0] = _value_0
2757 end
2758 end
2759 copy = _tab_0
2760end
2761local a = {
2762 1,
2763 2,
2764 3,
2765 x = 1
2766}
2767local b = {
2768 4,
2769 5,
2770 y = 1
2771}
2772local merge
2773local _tab_0 = { }
2774local _idx_0 = 1
2775for _key_0, _value_0 in pairs(a) do
2776 if _idx_0 == _key_0 then
2777 _tab_0[#_tab_0 + 1] = _value_0
2778 _idx_0 = _idx_0 + 1
2779 else
2780 _tab_0[_key_0] = _value_0
2781 end
2782end
2783local _idx_1 = 1
2784for _key_0, _value_0 in pairs(b) do
2785 if _idx_1 == _key_0 then
2786 _tab_0[#_tab_0 + 1] = _value_0
2787 _idx_1 = _idx_1 + 1
2788 else
2789 _tab_0[_key_0] = _value_0
2790 end
2791end
2792merge = _tab_0
2793local last
2794do
2795 local _item_0 = data.items
2796 last = _item_0[#_item_0]
2797end
2798local second_last
2799do
2800 local _item_0 = data.items
2801 second_last = _item_0[#_item_0 - 1]
2802end
2803local _obj_0 = data.items
2804_obj_0[#_obj_0] = 1
2805local mt = { }
2806local add
2807add = function(self, right)
2808 return setmetatable({
2809 value = self.value + right.value
2810 }, mt)
2811end
2812mt.__add = add
2813local a = setmetatable({
2814 value = 1
2815}, mt)
2816local b = setmetatable({
2817 value = 2
2818}, {
2819 __add = add
2820})
2821local c = setmetatable({
2822 value = 3
2823}, {
2824 __add = mt.__add
2825})
2826local d = a + b + c
2827print(d.value)
2828local _ <close> = setmetatable({ }, {
2829 __close = function()
2830 return print("out of scope")
2831 end
2832})
2833local tb = setmetatable({ }, {
2834 ["value"] = 123
2835})
2836getmetatable(tb).__index = getmetatable(tb)
2837print(tb.value)
2838setmetatable(tb, {
2839 __index = {
2840 item = "hello"
2841 }
2842})
2843print(tb.item)
2844local item, new, close, getter
2845do
2846 local _obj_0 = tb
2847 item, new = _obj_0[1], _obj_0.new
2848 do
2849 local _obj_1 = getmetatable(_obj_0)
2850 close, getter = _obj_1.__close, _obj_1.__index
2851 end
2852end
2853print(item, new, close, getter)
2854do
2855 local _obj_0 = func
2856 if _obj_0 ~= nil then
2857 _obj_0()
2858 end
2859end
2860print((function()
2861 local _obj_0 = abc
2862 if _obj_0 ~= nil then
2863 local _obj_1 = _obj_0["hello world"]
2864 if _obj_1 ~= nil then
2865 return _obj_1.xyz
2866 end
2867 return nil
2868 end
2869 return nil
2870end)())
2871local x
2872do
2873 local _obj_0 = tab
2874 if _obj_0 ~= nil then
2875 x = _obj_0.value
2876 end
2877end
2878local len = (function()
2879 local _obj_0 = utf8
2880 if _obj_0 ~= nil then
2881 return _obj_0.len
2882 end
2883 return nil
2884end)() or (function()
2885 local _obj_0 = string
2886 if _obj_0 ~= nil then
2887 return _obj_0.len
2888 end
2889 return nil
2890end)() or function(o)
2891 return #o
2892end
2893if print and (x ~= nil) then
2894 print(x)
2895end
2896local _with_0 = io.open("test.txt", "w")
2897if _with_0 ~= nil then
2898 _with_0:write("hello")
2899 _with_0:close()
2900end
2901print("hello")
2902print(1, 2)
2903print(1, 2, 3)
2904print(render(emit(parse(extract(readFile("example.txt"), language, { }), language))))
2905local a, b, c, d
2906if b ~= nil then
2907 a = b
2908else
2909 if c ~= nil then
2910 a = c
2911 else
2912 a = d
2913 end
2914end
2915func((function()
2916 if a ~= nil then
2917 return a
2918 else
2919 return { }
2920 end
2921end)())
2922if a == nil then
2923 a = false
2924end
2925local list = {
2926 1,
2927 2,
2928 3
2929}
2930func({
2931 1,
2932 2,
2933 3
2934})
2935local f
2936f = function()
2937 return {
2938 1,
2939 2,
2940 3
2941 }
2942end
2943local tb = {
2944 name = "abc",
2945 values = {
2946 "a",
2947 "b",
2948 "c"
2949 },
2950 objects = {
2951 {
2952 name = "a",
2953 value = 1,
2954 func = function(self)
2955 return self.value + 1
2956 end,
2957 tb = {
2958 fieldA = 1
2959 }
2960 },
2961 {
2962 name = "b",
2963 value = 2,
2964 func = function(self)
2965 return self.value + 2
2966 end,
2967 tb = { }
2968 }
2969 }
2970}
2971do
2972 local insert, concat = table.insert, table.concat
2973 local C, Ct, Cmt
2974 do
2975 local _obj_0 = require("lpeg")
2976 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
2977 end
2978 local x, y, z
2979 do
2980 local _obj_0 = require('mymodule')
2981 x, y, z = _obj_0.x, _obj_0.y, _obj_0.z
2982 end
2983 local a, b, c
2984 local _obj_0 = require('module')
2985 a, b, c = _obj_0.a, _obj_0.b, _obj_0.c
2986end
2987do
2988 local module = require('module')
2989 local module_x = require('module_x')
2990 local d_a_s_h_e_s = require("d-a-s-h-e-s")
2991 local part = require("module.part")
2992end
2993do
2994 local PlayerModule = require("player")
2995 local C, Ct, Cmt
2996 do
2997 local _obj_0 = require("lpeg")
2998 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
2999 end
3000 local one, two, ch
3001 local _obj_0 = require("export")
3002 one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1]
3003end
3004do
3005 local tostring <const> = tostring
3006 local concat <const> = table.concat
3007 print(concat({
3008 "a",
3009 tostring(1)
3010 }))
3011end
3012do
3013 local print <const> = print
3014 local math <const> = math
3015 print("hello")
3016 math.random(3)
3017end
3018do
3019 local print <const> = print
3020 print(FLAG)
3021 FLAG = 123
3022end
3023local _module_0 = { }
3024local a, b, c = 1, 2, 3
3025_module_0["a"], _module_0["b"], _module_0["c"] = a, b, c
3026local cool = "cat"
3027_module_0["cool"] = cool
3028local What
3029if this then
3030 What = "abc"
3031else
3032 What = "def"
3033end
3034_module_0["What"] = What
3035local y
3036y = function()
3037 local hallo = 3434
3038end
3039_module_0["y"] = y
3040local Something
3041local _class_0
3042local _base_0 = {
3043 umm = "cool"
3044}
3045if _base_0.__index == nil then
3046 _base_0.__index = _base_0
3047end
3048_class_0 = setmetatable({
3049 __init = function() end,
3050 __base = _base_0,
3051 __name = "Something"
3052}, {
3053 __index = _base_0,
3054 __call = function(cls, ...)
3055 local _self_0 = setmetatable({ }, _base_0)
3056 cls.__init(_self_0, ...)
3057 return _self_0
3058 end
3059})
3060_base_0.__class = _class_0
3061Something = _class_0
3062_module_0["Something"] = Something
3063return _module_0
3064local _module_0 = { }
3065local loadstring, tolua
3066do
3067 local _obj_0 = yue
3068 loadstring, tolua = _obj_0.loadstring, _obj_0.to_lua
3069end
3070_module_0["loadstring"], _module_0["tolua"] = loadstring, tolua
3071local fieldA = tb.itemA.fieldA
3072if fieldA == nil then
3073 fieldA = 'default'
3074end
3075_module_0["fieldA"] = fieldA
3076return _module_0
3077local _module_0 = setmetatable({ }, { })
3078_module_0.itemA = tb
3079getmetatable(_module_0).__index = items
3080_module_0["a-b-c"] = 123
3081return _module_0
3082local _module_0 = { }
3083local d, e, f = 3, 2, 1
3084_module_0[#_module_0 + 1] = d
3085_module_0[#_module_0 + 1] = e
3086_module_0[#_module_0 + 1] = f
3087if this then
3088 _module_0[#_module_0 + 1] = 123
3089else
3090 _module_0[#_module_0 + 1] = 456
3091end
3092local _with_0 = tmp
3093local j = 2000
3094_module_0[#_module_0 + 1] = _with_0
3095return _module_0
3096local _module_0 = nil
3097_module_0 = function()
3098 print("hello")
3099 return 123
3100end
3101return _module_0
3102local hello = "world"
3103local a, b, c = 1, 2, 3
3104hello = 123
3105local x = 1
3106x = x + 1
3107x = x - 1
3108x = x * 10
3109x = x / 10
3110x = x % 10
3111local s = s .. "world"
3112local arg = arg or "default value"
3113local a = 0
3114local b = 0
3115local c = 0
3116local d = 0
3117local e = 0
3118local x = f()
3119local y = x
3120local z = x
3121do
3122 local a = 1
3123 local x, y, z
3124 print("forward declare all variables as locals")
3125 x = function()
3126 return 1 + y + z
3127 end
3128 y, z = 2, 3
3129 instance = Item:new()
3130end
3131do
3132 local X = 1
3133 local B
3134 print("only forward declare upper case variables")
3135 local a = 1
3136 B = 2
3137end
3138do
3139 a = 1
3140 print("declare all variables as globals")
3141 x = function()
3142 return 1 + y + z
3143 end
3144 y, z = 2, 3
3145end
3146do
3147 X = 1
3148 print("only declare upper case variables as globals")
3149 local a = 1
3150 B = 2
3151 local Temp = "a local value"
3152end
3153local thing = {
3154 1,
3155 2
3156}
3157local a, b = thing[1], thing[2]
3158print(a, b)
3159local obj = {
3160 hello = "world",
3161 day = "tuesday",
3162 length = 20
3163}
3164local hello, the_day = obj.hello, obj.day
3165print(hello, the_day)
3166local day = obj.day
3167local obj2 = {
3168 numbers = {
3169 1,
3170 2,
3171 3,
3172 4
3173 },
3174 properties = {
3175 color = "green",
3176 height = 13.5
3177 }
3178}
3179local first, second = obj2.numbers[1], obj2.numbers[2]
3180print(first, second, color)
3181local first, second, color
3182local _obj_0 = obj2
3183first, second, color = _obj_0.numbers[1], _obj_0.numbers[2], _obj_0.properties.color
3184local concat, insert
3185local _obj_0 = table
3186concat, insert = _obj_0.concat, _obj_0.insert
3187local mix, max, rand
3188local _obj_0 = math
3189mix, max, rand = _obj_0.mix, _obj_0.max, _obj_0.random
3190local name, job
3191local _obj_0 = person
3192name, job = _obj_0.name, _obj_0.job
3193if name == nil then
3194 name = "nameless"
3195end
3196if job == nil then
3197 job = "jobless"
3198end
3199local two, four
3200local _obj_0 = items
3201two, four = _obj_0[2], _obj_0[4]
3202local orders = {
3203 "first",
3204 "second",
3205 "third",
3206 "fourth",
3207 "last"
3208}
3209local first, bulk, last = orders[1], (function()
3210 local _accum_0 = { }
3211 local _len_0 = 1
3212 local _max_0 = #orders + -2 + 1
3213 for _index_0 = 2, _max_0 do
3214 local _item_0 = orders[_index_0]
3215 _accum_0[_len_0] = _item_0
3216 _len_0 = _len_0 + 1
3217 end
3218 return _accum_0
3219end)(), orders[#orders]
3220print(first)
3221print(bulk)
3222print(last)
3223local first, rest
3224do
3225 local _obj_0 = orders
3226 first, rest = _obj_0[1], (function()
3227 local _accum_0 = { }
3228 local _len_0 = 1
3229 local _max_0 = #_obj_0
3230 for _index_0 = 2, _max_0 do
3231 local _item_0 = _obj_0[_index_0]
3232 _accum_0[_len_0] = _item_0
3233 _len_0 = _len_0 + 1
3234 end
3235 return _accum_0
3236 end)()
3237end
3238local start, last
3239do
3240 local _obj_0 = orders
3241 start, last = (function()
3242 local _accum_0 = { }
3243 local _len_0 = 1
3244 local _max_0 = #_obj_0 + -2 + 1
3245 for _index_0 = 1, _max_0 do
3246 local _item_0 = _obj_0[_index_0]
3247 _accum_0[_len_0] = _item_0
3248 _len_0 = _len_0 + 1
3249 end
3250 return _accum_0
3251 end)(), _obj_0[#_obj_0]
3252end
3253local _obj_0 = orders
3254first, last = _obj_0[1], _obj_0[#_obj_0]
3255local tuples = {
3256 {
3257 "hello",
3258 "world"
3259 },
3260 {
3261 "egg",
3262 "head"
3263 }
3264}
3265for _index_0 = 1, #tuples do
3266 local _des_0 = tuples[_index_0]
3267 local left, right = _des_0[1], _des_0[2]
3268 print(left, right)
3269end
3270local user = database.find_user("moon")
3271if user then
3272 print(user.name)
3273end
3274local hello = os.getenv("hello")
3275if hello then
3276 print("You have hello", hello)
3277else
3278 local world = os.getenv("world")
3279 if world then
3280 print("you have world", world)
3281 else
3282 print("nothing :(")
3283 end
3284end
3285do
3286 local success, result = pcall(function()
3287 return "get result without problems"
3288 end)
3289 if success then
3290 print(result)
3291 end
3292end
3293print("OK")
3294repeat
3295 local byte = stream:read_one()
3296 if byte then
3297 print(byte)
3298 else
3299 break
3300 end
3301until false
3302local list = {
3303 1,
3304 2,
3305 3,
3306 4,
3307 5
3308}
3309local fn
3310fn = function(ok)
3311 return ok, table.unpack(list)
3312end
3313(function(_arg_0, ...)
3314 local ok = _arg_0
3315 local count = select('#', ...)
3316 local first = select(1, ...)
3317 return print(ok, count, first)
3318end)(fn(true))
3319local a = 1
3320local b = 2
3321print(a + b)
3322Rx.Observable.fromRange(1, 8):filter(function(x)
3323 return x % 2 == 0
3324end):concat(Rx.Observable.of('who do we appreciate')):map(function(value)
3325 return value .. '!'
3326end):subscribe(print)
3327local str = strA .. strB .. strC
3328func(3000, "192.168.1.1")
3329xpcall(function()
3330 return func(1, 2, 3)
3331end, function(err)
3332 return print(yue.traceback(err))
3333end)
3334local success, result = xpcall(function()
3335 return func(1, 2, 3)
3336end, function(err)
3337 return yue.traceback(err)
3338end)
3339xpcall(function()
3340 return func(1, 2, 3)
3341end, function(err)
3342 return print(yue.traceback(err))
3343end)
3344success, result = pcall(function()
3345 return func(1, 2, 3)
3346end)
3347pcall(function()
3348 print("trying")
3349 return func(1, 2, 3)
3350end)
3351success, result = xpcall(function()
3352 return func(1, 2, 3)
3353end, function(err)
3354 return print(yue.traceback(err))
3355end)
3356if success then
3357 print(result)
3358end
3359local a, b, c
3360do
3361 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
3362 return func()
3363 end)
3364 if _ok_0 then
3365 a, b, c = _ret_0, _ret_1, _ret_2
3366 end
3367end
3368do
3369 local _exp_0 = ((function()
3370 return (function(_arg_0, ...)
3371 local _ok_0 = _arg_0
3372 if _ok_0 then
3373 return ...
3374 end
3375 end)(pcall(function()
3376 return func()
3377 end))
3378 end)())
3379 if _exp_0 ~= nil then
3380 a = _exp_0
3381 else
3382 a = "default"
3383 end
3384end
3385f((function()
3386 return (function(_arg_0, ...)
3387 local _ok_0 = _arg_0
3388 if _ok_0 then
3389 return ...
3390 end
3391 end)(pcall(function()
3392 return func()
3393 end))
3394end)())
3395f((function()
3396 return (function(_arg_0, ...)
3397 local _ok_0 = _arg_0
3398 if _ok_0 then
3399 return ...
3400 end
3401 end)(xpcall(function()
3402 print(123)
3403 return func()
3404 end, function(e)
3405 print(e)
3406 return e
3407 end))
3408end)())
3409local a <const> = 123
3410local _ <close> = setmetatable({ }, {
3411 __close = function()
3412 return print("Out of scope.")
3413 end
3414})
3415local a, b, c, d
3416local _obj_0 = tb
3417a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
3418Constant = 123
3419local some_string = "Here is a string\n that has a line break in it."
3420print("I am " .. tostring(math.random() * 100) .. "% sure.")
3421local integer = 1000000
3422local hex = 0xEFBBBF
3423local binary = 19
3424local str = "key: value\nlist:\n - item1\n - " .. tostring(expr)
3425local fn
3426fn = function()
3427 local str = "foo:\n bar: baz"
3428 return str
3429end
3430local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
3431local my_function
3432my_function = function() end
3433my_function()
3434local func_a
3435func_a = function()
3436 return print("hello world")
3437end
3438local func_b
3439func_b = function()
3440 local value = 100
3441 return print("The value:", value)
3442end
3443func_a()
3444func_b()
3445local sum
3446sum = function(x, y)
3447 return print("sum", x + y)
3448end
3449sum(10, 20)
3450print(sum(10, 20))
3451a(b(c("a", "b", "c")))
3452print("x:", sum(10, 20), "y:", sum(30, 40))
3453local sum
3454sum = function(x, y)
3455 return x + y
3456end
3457print("The sum is ", sum(10, 20))
3458local sum
3459sum = function(x, y)
3460 return x + y
3461end
3462local mystery
3463mystery = function(x, y)
3464 return x + y, x - y
3465end
3466local a, b = mystery(10, 20)
3467local func
3468func = function(self, num)
3469 return self.value + num
3470end
3471local my_function
3472my_function = function(name, height)
3473 if name == nil then
3474 name = "something"
3475 end
3476 if height == nil then
3477 height = 100
3478 end
3479 print("Hello I am", name)
3480 return print("My height is", height)
3481end
3482local some_args
3483some_args = function(x, y)
3484 if x == nil then
3485 x = 100
3486 end
3487 if y == nil then
3488 y = x + 1000
3489 end
3490 return print(x + y)
3491end
3492local a = x - 10
3493local b = x - 10
3494local c = x(-y)
3495local d = x - z
3496local x = func("hello") + 100
3497local y = func("hello" + 100)
3498my_func(5, 4, 3, 8, 9, 10)
3499cool_func(1, 2, 3, 4, 5, 6, 7, 8)
3500my_func(5, 6, 7, 6, another_func(6, 7, 8, 9, 1, 2), 5, 4)
3501local x = {
3502 1,
3503 2,
3504 3,
3505 4,
3506 a_func(4, 5, 5, 6),
3507 8,
3508 9,
3509 10
3510}
3511local y = {
3512 my_func(1, 2, 3, 4, 5),
3513 5,
3514 6,
3515 7
3516}
3517if func(1, 2, 3, "hello", "world") then
3518 print("hello")
3519 print("I am inside if")
3520end
3521if func(1, 2, 3, "hello", "world") then
3522 print("hello")
3523 print("I am inside if")
3524end
3525local f1
3526f1 = function(_arg_0)
3527 local a, b, c
3528 a, b, c = _arg_0.a, _arg_0.b, _arg_0.c
3529 return print(a, b, c)
3530end
3531f1({
3532 a = 1,
3533 b = "2",
3534 c = { }
3535})
3536local f2
3537f2 = function(_arg_0, c)
3538 local a1, b
3539 a1, b = _arg_0.a, _arg_0.b
3540 if a1 == nil then
3541 a1 = 123
3542 end
3543 if b == nil then
3544 b = 'abc'
3545 end
3546 if c == nil then
3547 c = { }
3548 end
3549end
3550print(a1, b, c)
3551local arg1 = {
3552 a = 0
3553}
3554f2(arg1, arg2)
3555local findFirstEven
3556findFirstEven = function(list)
3557 for _index_0 = 1, #list do
3558 local item = list[_index_0]
3559 if type(item) == "table" then
3560 for _index_1 = 1, #item do
3561 local sub = item[_index_1]
3562 if sub % 2 == 0 then
3563 return sub
3564 end
3565 end
3566 end
3567 end
3568 return nil
3569end
3570local findFirstEven
3571findFirstEven = function(list)
3572 for _index_0 = 1, #list do
3573 local item = list[_index_0]
3574 if type(item) == "table" then
3575 for _index_1 = 1, #item do
3576 local sub = item[_index_1]
3577 if sub % 2 == 0 then
3578 return sub
3579 end
3580 end
3581 end
3582 end
3583 return nil
3584end
3585local f
3586f = function(...)
3587 local t = {
3588 n = select("#", ...),
3589 ...
3590 }
3591 print("argument count:", t.n)
3592 print("table length:", #t)
3593 for i = 1, t.n do
3594 print(t[i])
3595 end
3596end
3597f(1, 2, 3)
3598f("a", "b", "c", "d")
3599f()
3600local process
3601process = function(...)
3602 local args = {
3603 n = select("#", ...),
3604 ...
3605 }
3606 local sum = 0
3607 for i = 1, args.n do
3608 if args[i] ~= nil and type(args[i]) == "number" then
3609 sum = sum + args[i]
3610 end
3611 end
3612 return sum
3613end
3614process(1, nil, 3, nil, 5)
3615f(function()
3616 return print("hello")
3617end)
3618f(function(self)
3619 return print(self.value)
3620end)
3621map(function(x)
3622 return x * 2
3623end, {
3624 1,
3625 2,
3626 3
3627})
3628local result, msg
3629do
3630 result, msg = readAsync("filename.txt", function(data)
3631 print(data)
3632 return processAsync(data, function(info)
3633 return check(info)
3634 end)
3635 end)
3636end
3637print(result, msg)
3638local some_values = {
3639 1,
3640 2,
3641 3,
3642 4
3643}
3644local some_values = {
3645 name = "Bill",
3646 age = 200,
3647 ["favorite food"] = "rice"
3648}
3649local profile = {
3650 height = "4 feet",
3651 shoe_size = 13,
3652 favorite_foods = {
3653 "ice cream",
3654 "donuts"
3655 }
3656}
3657local values = {
3658 1,
3659 2,
3660 3,
3661 4,
3662 5,
3663 6,
3664 7,
3665 8,
3666 name = "superman",
3667 occupation = "crime fighting"
3668}
3669my_function({
3670 dance = "Tango",
3671 partner = "none"
3672})
3673local y = {
3674 type = "dog",
3675 legs = 4,
3676 tails = 1
3677}
3678local tbl = {
3679 ["do"] = "something",
3680 ["end"] = "hunger"
3681}
3682local hair = "golden"
3683local height = 200
3684local person = {
3685 hair = hair,
3686 height = height,
3687 shoe_size = 40
3688}
3689print_table({
3690 hair = hair,
3691 height = height
3692})
3693local t = {
3694 [1 + 2] = "hello",
3695 ["hello world"] = true
3696}
3697local some_values = {
3698 1,
3699 2,
3700 3,
3701 4
3702}
3703local list_with_one_element = {
3704 1
3705}
3706local items = {
3707 1,
3708 2,
3709 3,
3710 4
3711}
3712local doubled
3713local _accum_0 = { }
3714local _len_0 = 1
3715for i, item in ipairs(items) do
3716 _accum_0[_len_0] = item * 2
3717 _len_0 = _len_0 + 1
3718end
3719doubled = _accum_0
3720local slice
3721local _accum_0 = { }
3722local _len_0 = 1
3723for i, item in ipairs(items) do
3724 if i > 1 and i < 3 then
3725 _accum_0[_len_0] = item
3726 _len_0 = _len_0 + 1
3727 end
3728end
3729slice = _accum_0
3730local doubled
3731local _accum_0 = { }
3732local _len_0 = 1
3733local _list_0 = items
3734for _index_0 = 1, #_list_0 do
3735 local item = _list_0[_index_0]
3736 _accum_0[_len_0] = item * 2
3737 _len_0 = _len_0 + 1
3738end
3739doubled = _accum_0
3740local data = {
3741 a = {
3742 1,
3743 2,
3744 3
3745 },
3746 b = {
3747 4,
3748 5,
3749 6
3750 }
3751}
3752local flat
3753local _accum_0 = { }
3754for k, v in pairs(data) do
3755 local _len_0 = #_accum_0 + 1
3756 for _index_0 = 1, #v do
3757 local _elm_0 = v[_index_0]
3758 _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1
3759 end
3760end
3761flat = _accum_0
3762local x_coords = {
3763 4,
3764 5,
3765 6,
3766 7
3767}
3768local y_coords = {
3769 9,
3770 2,
3771 3
3772}
3773local points
3774local _accum_0 = { }
3775local _len_0 = 1
3776for _index_0 = 1, #x_coords do
3777 local x = x_coords[_index_0]
3778 for _index_1 = 1, #y_coords do
3779 local y = y_coords[_index_1]
3780 _accum_0[_len_0] = {
3781 x,
3782 y
3783 }
3784 _len_0 = _len_0 + 1
3785 end
3786end
3787points = _accum_0
3788local evens
3789local _accum_0 = { }
3790local _len_0 = 1
3791for i = 1, 100 do
3792 if i % 2 == 0 then
3793 _accum_0[_len_0] = i
3794 _len_0 = _len_0 + 1
3795 end
3796end
3797evens = _accum_0
3798local thing = {
3799 color = "red",
3800 name = "fast",
3801 width = 123
3802}
3803local thing_copy
3804local _tbl_0 = { }
3805for k, v in pairs(thing) do
3806 _tbl_0[k] = v
3807end
3808thing_copy = _tbl_0
3809local no_color
3810local _tbl_0 = { }
3811for k, v in pairs(thing) do
3812 if k ~= "color" then
3813 _tbl_0[k] = v
3814 end
3815end
3816no_color = _tbl_0
3817local numbers = {
3818 1,
3819 2,
3820 3,
3821 4
3822}
3823local sqrts
3824local _tbl_0 = { }
3825for _index_0 = 1, #numbers do
3826 local i = numbers[_index_0]
3827 _tbl_0[i] = math.sqrt(i)
3828end
3829sqrts = _tbl_0
3830local tuples = {
3831 {
3832 "hello",
3833 "world"
3834 },
3835 {
3836 "foo",
3837 "bar"
3838 }
3839}
3840local tbl
3841local _tbl_0 = { }
3842for _index_0 = 1, #tuples do
3843 local tuple = tuples[_index_0]
3844 local _key_0, _val_0 = unpack(tuple)
3845 _tbl_0[_key_0] = _val_0
3846end
3847tbl = _tbl_0
3848local slice
3849local _accum_0 = { }
3850local _len_0 = 1
3851local _list_0 = items
3852for _index_0 = 1, 5 do
3853 local item = _list_0[_index_0]
3854 _accum_0[_len_0] = item
3855 _len_0 = _len_0 + 1
3856end
3857slice = _accum_0
3858local slice
3859local _accum_0 = { }
3860local _len_0 = 1
3861local _list_0 = items
3862local _max_0 = #_list_0
3863for _index_0 = 2, _max_0 do
3864 local item = _list_0[_index_0]
3865 _accum_0[_len_0] = item
3866 _len_0 = _len_0 + 1
3867end
3868slice = _accum_0
3869local slice
3870local _accum_0 = { }
3871local _len_0 = 1
3872local _list_0 = items
3873local _max_0 = #_list_0
3874for _index_0 = 1, _max_0, 2 do
3875 local item = _list_0[_index_0]
3876 _accum_0[_len_0] = item
3877 _len_0 = _len_0 + 1
3878end
3879slice = _accum_0
3880local slice
3881local _accum_0 = { }
3882local _len_0 = 1
3883local _list_0 = items
3884local _min_0 = #_list_0 + -4 + 1
3885local _max_0 = #_list_0 + -1 + 1
3886for _index_0 = _min_0, _max_0 do
3887 local item = _list_0[_index_0]
3888 _accum_0[_len_0] = item
3889 _len_0 = _len_0 + 1
3890end
3891slice = _accum_0
3892local reverse_slice
3893local _accum_0 = { }
3894local _len_0 = 1
3895local _list_0 = items
3896local _min_0 = #_list_0 + -1 + 1
3897for _index_0 = _min_0, 1, -1 do
3898 local item = _list_0[_index_0]
3899 _accum_0[_len_0] = item
3900 _len_0 = _len_0 + 1
3901end
3902reverse_slice = _accum_0
3903local sub_list
3904local _accum_0 = { }
3905local _len_0 = 1
3906local _list_0 = items
3907for _index_0 = 2, 4 do
3908 local _item_0 = _list_0[_index_0]
3909 _accum_0[_len_0] = _item_0
3910 _len_0 = _len_0 + 1
3911end
3912sub_list = _accum_0
3913for i = 10, 20 do
3914 print(i)
3915end
3916for k = 1, 15, 2 do
3917 print(k)
3918end
3919for key, value in pairs(object) do
3920 print(key, value)
3921end
3922local _list_0 = items
3923for _index_0 = 2, 4 do
3924 local item = _list_0[_index_0]
3925 print(item)
3926end
3927local _list_0 = items
3928for _index_0 = 1, #_list_0 do
3929 local item = _list_0[_index_0]
3930 print(item)
3931end
3932for j = 1, 10, 3 do
3933 print(j)
3934end
3935local doubled_evens
3936local _accum_0 = { }
3937local _len_0 = 1
3938for i = 1, 20 do
3939 if i % 2 == 0 then
3940 _accum_0[_len_0] = i * 2
3941 _len_0 = _len_0 + 1
3942 else
3943 _accum_0[_len_0] = i
3944 _len_0 = _len_0 + 1
3945 end
3946end
3947doubled_evens = _accum_0
3948local first_large
3949local _accum_0
3950local _list_0 = numbers
3951for _index_0 = 1, #_list_0 do
3952 local n = _list_0[_index_0]
3953 if n > 10 then
3954 _accum_0 = n
3955 break
3956 end
3957end
3958first_large = _accum_0
3959local func_a
3960func_a = function()
3961 for i = 1, 10 do
3962 print(i)
3963 end
3964end
3965local func_b
3966func_b = function()
3967 local _accum_0 = { }
3968 local _len_0 = 1
3969 for i = 1, 10 do
3970 _accum_0[_len_0] = i
3971 _len_0 = _len_0 + 1
3972 end
3973 return _accum_0
3974end
3975print(func_a())
3976print(func_b())
3977local i = 10
3978repeat
3979 print(i)
3980 i = i - 1
3981until i == 0
3982local i = 10
3983while i > 0 do
3984 print(i)
3985 i = i - 1
3986end
3987while running == true do
3988 my_function()
3989end
3990local i = 10
3991while not (i == 0) do
3992 print(i)
3993 i = i - 1
3994end
3995while not (running == false) do
3996 my_function()
3997end
3998local i = 0
3999while i < 10 do
4000 i = i + 1
4001 if i % 2 == 0 then
4002 goto _continue_0
4003 end
4004 print(i)
4005 ::_continue_0::
4006end
4007local my_numbers = {
4008 1,
4009 2,
4010 3,
4011 4,
4012 5,
4013 6
4014}
4015local odds
4016local _accum_0 = { }
4017local _len_0 = 1
4018for _index_0 = 1, #my_numbers do
4019 local x = my_numbers[_index_0]
4020 if x % 2 == 1 then
4021 goto _continue_0
4022 end
4023 _accum_0[_len_0] = x
4024 _len_0 = _len_0 + 1
4025 ::_continue_0::
4026end
4027odds = _accum_0
4028local have_coins = false
4029if have_coins then
4030 print("Got coins")
4031else
4032 print("No coins")
4033end
4034local have_coins = false
4035if have_coins then
4036 print("Got coins")
4037else
4038 print("No coins")
4039end
4040local have_coins = false
4041print((function()
4042 if have_coins then
4043 return "Got coins"
4044 else
4045 return "No coins"
4046 end
4047end)())
4048local is_tall
4049is_tall = function(name)
4050 if name == "Rob" then
4051 return true
4052 else
4053 return false
4054 end
4055end
4056local message
4057if is_tall("Rob") then
4058 message = "I am very tall"
4059else
4060 message = "I am not so tall"
4061end
4062print(message)
4063if not (os.date("%A") == "Monday") then
4064 print("it is not Monday!")
4065end
4066if not (math.random() > 0.1) then
4067 print("You're lucky!")
4068end
4069local a = 5
4070if (1 == a or 3 == a or 5 == a or 7 == a) then
4071 print("checking equality with discrete values")
4072end
4073if (function()
4074 local _check_0 = list
4075 for _index_0 = 1, #_check_0 do
4076 if _check_0[_index_0] == a then
4077 return true
4078 end
4079 end
4080 return false
4081end)() then
4082 print("checking if `a` is in a list")
4083end
4084if not (math.random() > 0.1) then
4085 print("You're lucky!")
4086end
4087if name == "Rob" then
4088 print("hello world")
4089end
4090local _list_0 = items
4091for _index_0 = 1, #_list_0 do
4092 local item = _list_0[_index_0]
4093 print("item: ", item)
4094end
4095while game:isRunning() do
4096 game:update()
4097end
4098while not reader:eof() do
4099 reader:parse_line()
4100end
4101local name = "Dan"
4102if "Robert" == name then
4103 print("You are Robert")
4104elseif "Dan" == name or "Daniel" == name then
4105 print("Your name, it's Dan")
4106else
4107 print("I don't know about you with name " .. tostring(name))
4108end
4109local b = 1
4110local next_number
4111if 1 == b then
4112 next_number = 2
4113elseif 2 == b then
4114 next_number = 3
4115else
4116 next_number = error("can't count that high!")
4117end
4118local msg
4119local _exp_0 = math.random(1, 5)
4120if 1 == _exp_0 then
4121 msg = "you are lucky"
4122elseif 2 == _exp_0 then
4123 msg = "you are almost lucky"
4124else
4125 msg = "not so lucky"
4126end
4127do
4128 local _exp_0 = math.random(1, 5)
4129 if 1 == _exp_0 then
4130 print("you are lucky")
4131 else
4132 print("not so lucky")
4133 end
4134end
4135local _exp_0 = math.random(1, 5)
4136if 1 == _exp_0 then
4137 print("you are lucky")
4138else
4139 print("not so lucky")
4140end
4141local items = {
4142 {
4143 x = 100,
4144 y = 200
4145 },
4146 {
4147 width = 300,
4148 height = 400
4149 }
4150}
4151for _index_0 = 1, #items do
4152 local item = items[_index_0]
4153 local _type_0 = type(item)
4154 local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4155 local _match_0 = false
4156 if _tab_0 then
4157 local x = item.x
4158 local y = item.y
4159 if x ~= nil and y ~= nil then
4160 _match_0 = true
4161 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
4162 end
4163 end
4164 if not _match_0 then
4165 if _tab_0 then
4166 local width = item.width
4167 local height = item.height
4168 if width ~= nil and height ~= nil then
4169 print("size " .. tostring(width) .. ", " .. tostring(height))
4170 end
4171 end
4172 end
4173end
4174local item = { }
4175local x, y = item.pos.x, item.pos.y
4176if x == nil then
4177 x = 50
4178end
4179if y == nil then
4180 y = 200
4181end
4182local _type_0 = type(item)
4183local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4184if _tab_0 then
4185 do
4186 local _obj_0 = item.pos
4187 local _type_1 = type(_obj_0)
4188 if "table" == _type_1 or "userdata" == _type_1 then
4189 x = _obj_0.x
4190 end
4191 end
4192 do
4193 local _obj_0 = item.pos
4194 local _type_1 = type(_obj_0)
4195 if "table" == _type_1 or "userdata" == _type_1 then
4196 y = _obj_0.y
4197 end
4198 end
4199 if x == nil then
4200 x = 50
4201 end
4202 if y == nil then
4203 y = 200
4204 end
4205 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
4206end
4207local _exp_0 = tb
4208local _type_0 = type(_exp_0)
4209local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4210local _match_0 = false
4211if _tab_0 then
4212 if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then
4213 _match_0 = true
4214 print("1, 2, 3")
4215 end
4216end
4217if not _match_0 then
4218 local _match_1 = false
4219 if _tab_0 then
4220 local b = _exp_0[2]
4221 if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then
4222 _match_1 = true
4223 print("1, " .. tostring(b) .. ", 3")
4224 end
4225 end
4226 if not _match_1 then
4227 if _tab_0 then
4228 local b = _exp_0[3]
4229 if b == nil then
4230 b = 3
4231 end
4232 if 1 == _exp_0[1] and 2 == _exp_0[2] then
4233 print("1, 2, " .. tostring(b))
4234 end
4235 end
4236 end
4237end
4238local _exp_0 = tb
4239local _type_0 = type(_exp_0)
4240local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4241local _match_0 = false
4242if _tab_0 then
4243 local result = _exp_0.result
4244 if true == _exp_0.success and result ~= nil then
4245 _match_0 = true
4246 print("success", result)
4247 end
4248end
4249if not _match_0 then
4250 local _match_1 = false
4251 if _tab_0 then
4252 if false == _exp_0.success then
4253 _match_1 = true
4254 print("failed", result)
4255 end
4256 end
4257 if not _match_1 then
4258 print("invalid")
4259 end
4260end
4261local _exp_0 = tb
4262local _type_0 = type(_exp_0)
4263local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4264local _match_0 = false
4265if _tab_0 then
4266 local content
4267 do
4268 local _obj_0 = _exp_0.data
4269 local _type_1 = type(_obj_0)
4270 if "table" == _type_1 or "userdata" == _type_1 then
4271 content = _obj_0.content
4272 end
4273 end
4274 local _val_0
4275 do
4276 local _obj_0 = _exp_0.data
4277 if _obj_0 ~= nil then
4278 _val_0 = _obj_0.type
4279 end
4280 end
4281 if "success" == _val_0 and content ~= nil then
4282 _match_0 = true
4283 print("success", content)
4284 end
4285end
4286if not _match_0 then
4287 local _match_1 = false
4288 if _tab_0 then
4289 local content
4290 do
4291 local _obj_0 = _exp_0.data
4292 local _type_1 = type(_obj_0)
4293 if "table" == _type_1 or "userdata" == _type_1 then
4294 content = _obj_0.content
4295 end
4296 end
4297 local _val_0
4298 do
4299 local _obj_0 = _exp_0.data
4300 if _obj_0 ~= nil then
4301 _val_0 = _obj_0.type
4302 end
4303 end
4304 if "error" == _val_0 and content ~= nil then
4305 _match_1 = true
4306 print("failed", content)
4307 end
4308 end
4309 if not _match_1 then
4310 print("invalid")
4311 end
4312end
4313local _exp_0 = tb
4314local _type_0 = type(_exp_0)
4315local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4316if _tab_0 then
4317 local fourth = _exp_0[4]
4318 local _val_0
4319 do
4320 local _obj_0 = _exp_0[1]
4321 if _obj_0 ~= nil then
4322 _val_0 = _obj_0.a
4323 end
4324 end
4325 local _val_1
4326 do
4327 local _obj_0 = _exp_0[1]
4328 if _obj_0 ~= nil then
4329 _val_1 = _obj_0.b
4330 end
4331 end
4332 local _val_2
4333 do
4334 local _obj_0 = _exp_0[2]
4335 if _obj_0 ~= nil then
4336 _val_2 = _obj_0.a
4337 end
4338 end
4339 local _val_3
4340 do
4341 local _obj_0 = _exp_0[2]
4342 if _obj_0 ~= nil then
4343 _val_3 = _obj_0.b
4344 end
4345 end
4346 local _val_4
4347 do
4348 local _obj_0 = _exp_0[3]
4349 if _obj_0 ~= nil then
4350 _val_4 = _obj_0.a
4351 end
4352 end
4353 local _val_5
4354 do
4355 local _obj_0 = _exp_0[3]
4356 if _obj_0 ~= nil then
4357 _val_5 = _obj_0.b
4358 end
4359 end
4360 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
4361 print("matched", fourth)
4362 end
4363end
4364local segments = {
4365 "admin",
4366 "users",
4367 "logs",
4368 "view"
4369}
4370local _type_0 = type(segments)
4371local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4372if _tab_0 then
4373 local groups
4374 do
4375 local _accum_0 = { }
4376 local _len_0 = 1
4377 local _max_0 = #segments + -3 + 1
4378 for _index_0 = 1, _max_0 do
4379 local _item_0 = segments[_index_0]
4380 _accum_0[_len_0] = _item_0
4381 _len_0 = _len_0 + 1
4382 end
4383 groups = _accum_0
4384 end
4385 local resource = segments[#segments - 1]
4386 local action = segments[#segments]
4387 if resource ~= nil and action ~= nil then
4388 print("Group:", groups)
4389 print("Resource:", resource)
4390 print("Action:", action)
4391 end
4392end
4393local Inventory 4313local Inventory
4394local _class_0 4314local _class_0
4395local _base_0 = { 4315local _base_0 = {
@@ -5050,6 +4970,46 @@ local _with_0 = obj
5050if _with_0 ~= nil then 4970if _with_0 ~= nil then
5051 print(obj.name) 4971 print(obj.name)
5052end 4972end
4973local _with_0 = Person()
4974_with_0.name = "Oswald"
4975_with_0:add_relative(my_dad)
4976_with_0:save()
4977print(_with_0.name)
4978local file
4979local _with_0 = File("favorite_foods.txt")
4980_with_0:set_encoding("utf8")
4981file = _with_0
4982local create_person
4983create_person = function(name, relatives)
4984 local _with_0 = Person()
4985 _with_0.name = name
4986 for _index_0 = 1, #relatives do
4987 local relative = relatives[_index_0]
4988 _with_0:add_relative(relative)
4989 end
4990 return _with_0
4991end
4992local me = create_person("Leaf", {
4993 dad,
4994 mother,
4995 sister
4996})
4997local str = "Hello"
4998print("original:", str)
4999print("upper:", str:upper())
5000local _with_0 = tb
5001_with_0[1] = 1
5002print(_with_0[2])
5003do
5004 local _with_1 = _with_0[abc]
5005 _with_1[3] = _with_1[2]:func()
5006 _with_1["key-name"] = value
5007end
5008_with_0[#_with_0 + 1] = "abc"
5009local _with_0 = obj
5010if _with_0 ~= nil then
5011 print(obj.name)
5012end
5053do 5013do
5054 local var = "hello" 5014 local var = "hello"
5055 print(var) 5015 print(var)
@@ -5071,6 +5031,46 @@ local tbl = {
5071 return 1234 5031 return 1234
5072 end)() 5032 end)()
5073} 5033}
5034do
5035 local var = "hello"
5036 print(var)
5037end
5038print(var)
5039local counter
5040do
5041 local i = 0
5042 counter = function()
5043 i = i + 1
5044 return i
5045 end
5046end
5047print(counter())
5048print(counter())
5049local tbl = {
5050 key = (function()
5051 print("assigning key!")
5052 return 1234
5053 end)()
5054}
5055local my_object = {
5056 value = 1000,
5057 write = function(self)
5058 return print("the value:", self.value)
5059 end
5060}
5061local run_callback
5062run_callback = function(func)
5063 print("running callback...")
5064 return func()
5065end
5066run_callback(my_object.write)
5067run_callback((function()
5068 local _base_0 = my_object
5069 local _fn_0 = _base_0.write
5070 return _fn_0 and function(...)
5071 return _fn_0(_base_0, ...)
5072 end
5073end)())
5074local my_object = { 5074local my_object = {
5075 value = 1000, 5075 value = 1000,
5076 write = function(self) 5076 write = function(self)
@@ -5118,3 +5118,31 @@ my_func = function(add)
5118end 5118end
5119my_func(22) 5119my_func(22)
5120print(i, k) 5120print(i, k)
5121local i = 100
5122local my_func
5123my_func = function()
5124 i = 10
5125 while i > 0 do
5126 print(i)
5127 i = i - 1
5128 end
5129end
5130my_func()
5131print(i)
5132local i = 100
5133local my_func
5134my_func = function()
5135 local i = "hello"
5136end
5137my_func()
5138print(i)
5139local tmp = 1213
5140local i, k = 100, 50
5141local my_func
5142my_func = function(add)
5143 local tmp = tmp + add
5144 i = i + tmp
5145 k = k + tmp
5146end
5147my_func(22)
5148print(i, k)
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua
index 2aa354e..f4ef2c7 100644
--- a/spec/outputs/codes_from_doc_zh.lua
+++ b/spec/outputs/codes_from_doc_zh.lua
@@ -76,6 +76,84 @@ end
76local _u1f31b = "月之脚本" 76local _u1f31b = "月之脚本"
77_module_0["🌛"] = _u1f31b 77_module_0["🌛"] = _u1f31b
78return _module_0 78return _module_0
79local _module_0 = { }
80local p, to_lua
81do
82 local _obj_0 = require("yue")
83 p, to_lua = _obj_0.p, _obj_0.to_lua
84end
85local inventory = {
86 equipment = {
87 "sword",
88 "shield"
89 },
90 items = {
91 {
92 name = "potion",
93 count = 10
94 },
95 {
96 name = "bread",
97 count = 3
98 }
99 }
100}
101local map
102map = function(arr, action)
103 local _accum_0 = { }
104 local _len_0 = 1
105 for _index_0 = 1, #arr do
106 local item = arr[_index_0]
107 _accum_0[_len_0] = action(item)
108 _len_0 = _len_0 + 1
109 end
110 return _accum_0
111end
112local filter
113filter = function(arr, cond)
114 local _accum_0 = { }
115 local _len_0 = 1
116 for _index_0 = 1, #arr do
117 local item = arr[_index_0]
118 if cond(item) then
119 _accum_0[_len_0] = item
120 _len_0 = _len_0 + 1
121 end
122 end
123 return _accum_0
124end
125local reduce
126reduce = function(arr, init, action)
127 for _index_0 = 1, #arr do
128 local item = arr[_index_0]
129 init = action(init, item)
130 end
131 return init
132end
133print(reduce(filter(map({
134 1,
135 2,
136 3
137}, function(x)
138 return x * 2
139end), function(x)
140 return x > 4
141end), 0, function(a, b)
142 return a + b
143end))
144local apple = setmetatable({
145 size = 15,
146}, {
147 __index = {
148 color = 0x00ffff
149 }
150})
151if (getmetatable(apple) ~= nil) then
152 p(apple.size, apple.color, getmetatable(apple).__index)
153end
154local _u1f31b = "月之脚本"
155_module_0["🌛"] = _u1f31b
156return _module_0
79local area = 6.2831853071796 * 5 157local area = 6.2831853071796 * 5
80print('你好 世界') 158print('你好 世界')
81do 159do
@@ -115,6 +193,338 @@ end
115do 193do
116 print(123, "hello") 194 print(123, "hello")
117end 195end
196local area = 6.2831853071796 * 5
197print('你好 世界')
198do
199 assert(item ~= nil)
200end
201local value = item
202if (f1() and f2() and f3()) then
203 print("OK")
204end
205do
206 local funcA
207 funcA = function() end
208end
209local funcA
210funcA = function()
211 return "无法访问宏生成月之脚本里定义的变量"
212end
213do
214local function funcB() end
215end
216local funcB
217funcB = function()
218 return "无法访问宏生成 Lua 代码里定义的变量"
219end
220do
221-- 插入原始Lua代码
222if cond then
223 print("输出")
224end
225end
226print("yuescript")
227print(2)
228print("有效的枚举类型:", "Static")
229do
230 print(123, "hello")
231end
232do
233 print(123, "hello")
234end
235if tb ~= nil then
236 tb:func()
237end
238if tb ~= nil then
239 tb:func()
240end
241print(1 < 2 and 2 <= 2 and 2 < 3 and 3 == 3 and 3 > 2 and 2 >= 1 and 1 == 1 and 1 < 3 and 3 ~= 5)
242local a = 5
243print(1 <= a and a <= 10)
244local v
245v = function(x)
246 print(x)
247 return x
248end
249print((function()
250 local _cond_0 = v(2)
251 if not (v(1) < _cond_0) then
252 return false
253 else
254 return _cond_0 <= v(3)
255 end
256end)())
257print((function()
258 local _cond_0 = v(2)
259 if not (v(1) > _cond_0) then
260 return false
261 else
262 return _cond_0 <= v(3)
263 end
264end)())
265local tab = { }
266tab[#tab + 1] = "Value"
267local tbA = {
268 1,
269 2,
270 3
271}
272local tbB = {
273 4,
274 5,
275 6
276}
277local _len_0 = #tbA + 1
278for _index_0 = 1, #tbB do
279 local _elm_0 = tbB[_index_0]
280 tbA[_len_0], _len_0 = _elm_0, _len_0 + 1
281end
282local parts = {
283 "shoulders",
284 "knees"
285}
286local lyrics
287do
288 local _tab_0 = {
289 "head"
290 }
291 local _idx_0 = 1
292 for _key_0, _value_0 in pairs(parts) do
293 if _idx_0 == _key_0 then
294 _tab_0[#_tab_0 + 1] = _value_0
295 _idx_0 = _idx_0 + 1
296 else
297 _tab_0[_key_0] = _value_0
298 end
299 end
300 _tab_0[#_tab_0 + 1] = "and"
301 _tab_0[#_tab_0 + 1] = "toes"
302 lyrics = _tab_0
303end
304local copy
305do
306 local _tab_0 = { }
307 local _idx_0 = 1
308 for _key_0, _value_0 in pairs(other) do
309 if _idx_0 == _key_0 then
310 _tab_0[#_tab_0 + 1] = _value_0
311 _idx_0 = _idx_0 + 1
312 else
313 _tab_0[_key_0] = _value_0
314 end
315 end
316 copy = _tab_0
317end
318local a = {
319 1,
320 2,
321 3,
322 x = 1
323}
324local b = {
325 4,
326 5,
327 y = 1
328}
329local merge
330local _tab_0 = { }
331local _idx_0 = 1
332for _key_0, _value_0 in pairs(a) do
333 if _idx_0 == _key_0 then
334 _tab_0[#_tab_0 + 1] = _value_0
335 _idx_0 = _idx_0 + 1
336 else
337 _tab_0[_key_0] = _value_0
338 end
339end
340local _idx_1 = 1
341for _key_0, _value_0 in pairs(b) do
342 if _idx_1 == _key_0 then
343 _tab_0[#_tab_0 + 1] = _value_0
344 _idx_1 = _idx_1 + 1
345 else
346 _tab_0[_key_0] = _value_0
347 end
348end
349merge = _tab_0
350local last
351do
352 local _item_0 = data.items
353 last = _item_0[#_item_0]
354end
355local second_last
356do
357 local _item_0 = data.items
358 second_last = _item_0[#_item_0 - 1]
359end
360local _obj_0 = data.items
361_obj_0[#_obj_0] = 1
362local mt = { }
363local add
364add = function(self, right)
365 return setmetatable({
366 value = self.value + right.value
367 }, mt)
368end
369mt.__add = add
370local a = setmetatable({
371 value = 1
372}, mt)
373local b = setmetatable({
374 value = 2
375}, {
376 __add = add
377})
378local c = setmetatable({
379 value = 3
380}, {
381 __add = mt.__add
382})
383local d = a + b + c
384print(d.value)
385local _ <close> = setmetatable({ }, {
386 __close = function()
387 return print("超出范围")
388 end
389})
390local tb = setmetatable({ }, {
391 ["value"] = 123
392})
393getmetatable(tb).__index = getmetatable(tb)
394print(tb.value)
395setmetatable(tb, {
396 __index = {
397 item = "hello"
398 }
399})
400print(tb.item)
401local item, new, close, getter
402do
403 local _obj_0 = tb
404 item, new = _obj_0[1], _obj_0.new
405 do
406 local _obj_1 = getmetatable(_obj_0)
407 close, getter = _obj_1.__close, _obj_1.__index
408 end
409end
410print(item, new, close, getter)
411do
412 local _obj_0 = func
413 if _obj_0 ~= nil then
414 _obj_0()
415 end
416end
417print((function()
418 local _obj_0 = abc
419 if _obj_0 ~= nil then
420 local _obj_1 = _obj_0["你好 世界"]
421 if _obj_1 ~= nil then
422 return _obj_1.xyz
423 end
424 return nil
425 end
426 return nil
427end)())
428local x
429do
430 local _obj_0 = tab
431 if _obj_0 ~= nil then
432 x = _obj_0.value
433 end
434end
435local len = (function()
436 local _obj_0 = utf8
437 if _obj_0 ~= nil then
438 return _obj_0.len
439 end
440 return nil
441end)() or (function()
442 local _obj_0 = string
443 if _obj_0 ~= nil then
444 return _obj_0.len
445 end
446 return nil
447end)() or function(o)
448 return #o
449end
450if print and (x ~= nil) then
451 print(x)
452end
453local _with_0 = io.open("test.txt", "w")
454if _with_0 ~= nil then
455 _with_0:write("你好")
456 _with_0:close()
457end
458print("你好")
459print(1, 2)
460print(1, 2, 3)
461print(render(emit(parse(extract(readFile("example.txt"), language, { }), language))))
462local a, b, c, d
463if b ~= nil then
464 a = b
465else
466 if c ~= nil then
467 a = c
468 else
469 a = d
470 end
471end
472func((function()
473 if a ~= nil then
474 return a
475 else
476 return { }
477 end
478end)())
479if a == nil then
480 a = false
481end
482local list = {
483 1,
484 2,
485 3
486}
487func({
488 1,
489 2,
490 3
491})
492local f
493f = function()
494 return {
495 1,
496 2,
497 3
498 }
499end
500local tb = {
501 name = "abc",
502 values = {
503 "a",
504 "b",
505 "c"
506 },
507 objects = {
508 {
509 name = "a",
510 value = 1,
511 func = function(self)
512 return self.value + 1
513 end,
514 tb = {
515 fieldA = 1
516 }
517 },
518 {
519 name = "b",
520 value = 2,
521 func = function(self)
522 return self.value + 2
523 end,
524 tb = { }
525 }
526 }
527}
118if tb ~= nil then 528if tb ~= nil then
119 tb:func() 529 tb:func()
120end 530end
@@ -539,6 +949,188 @@ _module_0 = function()
539 return 123 949 return 123
540end 950end
541return _module_0 951return _module_0
952do
953 local insert, concat = table.insert, table.concat
954 local C, Ct, Cmt
955 do
956 local _obj_0 = require("lpeg")
957 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
958 end
959 local x, y, z
960 do
961 local _obj_0 = require('mymodule')
962 x, y, z = _obj_0.x, _obj_0.y, _obj_0.z
963 end
964 local a, b, c
965 local _obj_0 = require('module')
966 a, b, c = _obj_0.a, _obj_0.b, _obj_0.c
967end
968do
969 local module = require('module')
970 local module_x = require('module_x')
971 local d_a_s_h_e_s = require("d-a-s-h-e-s")
972 local part = require("module.part")
973end
974do
975 local PlayerModule = require("player")
976 local C, Ct, Cmt
977 do
978 local _obj_0 = require("lpeg")
979 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
980 end
981 local one, two, ch
982 local _obj_0 = require("export")
983 one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1]
984end
985do
986 local tostring <const> = tostring
987 local concat <const> = table.concat
988 print(concat({
989 "a",
990 tostring(1)
991 }))
992end
993do
994 local print <const> = print
995 local math <const> = math
996 print("hello")
997 math.random(3)
998end
999do
1000 local print <const> = print
1001 print(FLAG)
1002 FLAG = 123
1003end
1004local _module_0 = { }
1005local a, b, c = 1, 2, 3
1006_module_0["a"], _module_0["b"], _module_0["c"] = a, b, c
1007local cool = "cat"
1008_module_0["cool"] = cool
1009local What
1010if this then
1011 What = "abc"
1012else
1013 What = "def"
1014end
1015_module_0["What"] = What
1016local y
1017y = function()
1018 local hallo = 3434
1019end
1020_module_0["y"] = y
1021local Something
1022local _class_0
1023local _base_0 = {
1024 umm = "cool"
1025}
1026if _base_0.__index == nil then
1027 _base_0.__index = _base_0
1028end
1029_class_0 = setmetatable({
1030 __init = function() end,
1031 __base = _base_0,
1032 __name = "Something"
1033}, {
1034 __index = _base_0,
1035 __call = function(cls, ...)
1036 local _self_0 = setmetatable({ }, _base_0)
1037 cls.__init(_self_0, ...)
1038 return _self_0
1039 end
1040})
1041_base_0.__class = _class_0
1042Something = _class_0
1043_module_0["Something"] = Something
1044return _module_0
1045local _module_0 = { }
1046local loadstring, tolua
1047do
1048 local _obj_0 = yue
1049 loadstring, tolua = _obj_0.loadstring, _obj_0.to_lua
1050end
1051_module_0["loadstring"], _module_0["tolua"] = loadstring, tolua
1052local fieldA = tb.itemA.fieldA
1053if fieldA == nil then
1054 fieldA = '默认值'
1055end
1056_module_0["fieldA"] = fieldA
1057return _module_0
1058local _module_0 = setmetatable({ }, { })
1059_module_0.itemA = tb
1060getmetatable(_module_0).__index = items
1061_module_0["a-b-c"] = 123
1062return _module_0
1063local _module_0 = { }
1064local d, e, f = 3, 2, 1
1065_module_0[#_module_0 + 1] = d
1066_module_0[#_module_0 + 1] = e
1067_module_0[#_module_0 + 1] = f
1068if this then
1069 _module_0[#_module_0 + 1] = 123
1070else
1071 _module_0[#_module_0 + 1] = 456
1072end
1073local _with_0 = tmp
1074local j = 2000
1075_module_0[#_module_0 + 1] = _with_0
1076return _module_0
1077local _module_0 = nil
1078_module_0 = function()
1079 print("你好")
1080 return 123
1081end
1082return _module_0
1083local hello = "world"
1084local a, b, c = 1, 2, 3
1085hello = 123
1086local x = 1
1087x = x + 1
1088x = x - 1
1089x = x * 10
1090x = x / 10
1091x = x % 10
1092local s = s .. "world"
1093local arg = arg or "默认值"
1094local a = 0
1095local b = 0
1096local c = 0
1097local d = 0
1098local e = 0
1099local x = f()
1100local y = x
1101local z = x
1102do
1103 local a = 1
1104 local x, y, z
1105 print("预先声明后续所有变量为局部变量")
1106 x = function()
1107 return 1 + y + z
1108 end
1109 y, z = 2, 3
1110 instance = Item:new()
1111end
1112do
1113 local X = 1
1114 local B
1115 print("只预先声明后续大写的变量为局部变量")
1116 local a = 1
1117 B = 2
1118end
1119do
1120 a = 1
1121 print("预先声明所有变量为全局变量")
1122 x = function()
1123 return 1 + y + z
1124 end
1125 y, z = 2, 3
1126end
1127do
1128 x = 1
1129 print("只预先声明大写的变量为全局变量")
1130 local a = 1
1131 B = 2
1132 local Temp = "一个局部值"
1133end
542local hello = "world" 1134local hello = "world"
543local a, b, c = 1, 2, 3 1135local a, b, c = 1, 2, 3
544hello = 123 1136hello = 123
@@ -707,6 +1299,155 @@ for _index_0 = 1, #tuples do
707 local left, right = _des_0[1], _des_0[2] 1299 local left, right = _des_0[1], _des_0[2]
708 print(left, right) 1300 print(left, right)
709end 1301end
1302local thing = {
1303 1,
1304 2
1305}
1306local a, b = thing[1], thing[2]
1307print(a, b)
1308local obj = {
1309 hello = "world",
1310 day = "tuesday",
1311 length = 20
1312}
1313local hello, the_day = obj.hello, obj.day
1314print(hello, the_day)
1315local day = obj.day
1316local obj2 = {
1317 numbers = {
1318 1,
1319 2,
1320 3,
1321 4
1322 },
1323 properties = {
1324 color = "green",
1325 height = 13.5
1326 }
1327}
1328local first, second = obj2.numbers[1], obj2.numbers[2]
1329print(first, second, color)
1330local first, second, color
1331local _obj_0 = obj2
1332first, second, color = _obj_0.numbers[1], _obj_0.numbers[2], _obj_0.properties.color
1333local concat, insert
1334local _obj_0 = table
1335concat, insert = _obj_0.concat, _obj_0.insert
1336local mix, max, rand
1337local _obj_0 = math
1338mix, max, rand = _obj_0.mix, _obj_0.max, _obj_0.random
1339local name, job
1340local _obj_0 = person
1341name, job = _obj_0.name, _obj_0.job
1342if name == nil then
1343 name = "nameless"
1344end
1345if job == nil then
1346 job = "jobless"
1347end
1348local two, four
1349local _obj_0 = items
1350two, four = _obj_0[2], _obj_0[4]
1351local orders = {
1352 "first",
1353 "second",
1354 "third",
1355 "fourth",
1356 "last"
1357}
1358local first, bulk, last = orders[1], (function()
1359 local _accum_0 = { }
1360 local _len_0 = 1
1361 local _max_0 = #orders + -2 + 1
1362 for _index_0 = 2, _max_0 do
1363 local _item_0 = orders[_index_0]
1364 _accum_0[_len_0] = _item_0
1365 _len_0 = _len_0 + 1
1366 end
1367 return _accum_0
1368end)(), orders[#orders]
1369print(first)
1370print(bulk)
1371print(last)
1372local first, rest
1373do
1374 local _obj_0 = orders
1375 first, rest = _obj_0[1], (function()
1376 local _accum_0 = { }
1377 local _len_0 = 1
1378 local _max_0 = #_obj_0
1379 for _index_0 = 2, _max_0 do
1380 local _item_0 = _obj_0[_index_0]
1381 _accum_0[_len_0] = _item_0
1382 _len_0 = _len_0 + 1
1383 end
1384 return _accum_0
1385 end)()
1386end
1387local start, last
1388do
1389 local _obj_0 = orders
1390 start, last = (function()
1391 local _accum_0 = { }
1392 local _len_0 = 1
1393 local _max_0 = #_obj_0 + -2 + 1
1394 for _index_0 = 1, _max_0 do
1395 local _item_0 = _obj_0[_index_0]
1396 _accum_0[_len_0] = _item_0
1397 _len_0 = _len_0 + 1
1398 end
1399 return _accum_0
1400 end)(), _obj_0[#_obj_0]
1401end
1402local _obj_0 = orders
1403first, last = _obj_0[1], _obj_0[#_obj_0]
1404local tuples = {
1405 {
1406 "hello",
1407 "world"
1408 },
1409 {
1410 "egg",
1411 "head"
1412 }
1413}
1414for _index_0 = 1, #tuples do
1415 local _des_0 = tuples[_index_0]
1416 local left, right = _des_0[1], _des_0[2]
1417 print(left, right)
1418end
1419local user = database.find_user("moon")
1420if user then
1421 print(user.name)
1422end
1423local hello = os.getenv("hello")
1424if hello then
1425 print("你有 hello", hello)
1426else
1427 local world = os.getenv("world")
1428 if world then
1429 print("你有 world", world)
1430 else
1431 print("什么都没有 :(")
1432 end
1433end
1434do
1435 local success, result = pcall(function()
1436 return "无报错地获取结果"
1437 end)
1438 if success then
1439 print(result)
1440 end
1441end
1442print("好的")
1443repeat
1444 local byte = stream:read_one()
1445 if byte then
1446 print(byte)
1447 else
1448 break
1449 end
1450until false
710local user = database.find_user("moon") 1451local user = database.find_user("moon")
711if user then 1452if user then
712 print(user.name) 1453 print(user.name)
@@ -756,6 +1497,23 @@ end
756 local first = select(1, ...) 1497 local first = select(1, ...)
757 return print(ok, count, first) 1498 return print(ok, count, first)
758end)(fn(true)) 1499end)(fn(true))
1500local list = {
1501 1,
1502 2,
1503 3,
1504 4,
1505 5
1506}
1507local fn
1508fn = function(ok)
1509 return ok, table.unpack(list)
1510end
1511(function(_arg_0, ...)
1512 local ok = _arg_0
1513 local count = select('#', ...)
1514 local first = select(1, ...)
1515 return print(ok, count, first)
1516end)(fn(true))
759local a = 1 1517local a = 1
760local b = 2 1518local b = 2
761print(a + b) 1519print(a + b)
@@ -764,6 +1522,16 @@ Rx.Observable.fromRange(1, 8):filter(function(x)
764end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) 1522end):concat(Rx.Observable.of('who do we appreciate')):map(function(value)
765 return value .. '!' 1523 return value .. '!'
766end):subscribe(print) 1524end):subscribe(print)
1525local a = 1
1526local b = 2
1527print(a + b)
1528Rx.Observable.fromRange(1, 8):filter(function(x)
1529 return x % 2 == 0
1530end):concat(Rx.Observable.of('who do we appreciate')):map(function(value)
1531 return value .. '!'
1532end):subscribe(print)
1533local str = strA .. strB .. strC
1534func(3000, "192.168.1.1")
767local str = strA .. strB .. strC 1535local str = strA .. strB .. strC
768func(3000, "192.168.1.1") 1536func(3000, "192.168.1.1")
769xpcall(function() 1537xpcall(function()
@@ -846,6 +1614,96 @@ f((function()
846 return e 1614 return e
847 end)) 1615 end))
848end)()) 1616end)())
1617xpcall(function()
1618 return func(1, 2, 3)
1619end, function(err)
1620 return print(yue.traceback(err))
1621end)
1622local success, result = xpcall(function()
1623 return func(1, 2, 3)
1624end, function(err)
1625 return yue.traceback(err)
1626end)
1627xpcall(function()
1628 return func(1, 2, 3)
1629end, function(err)
1630 return print(yue.traceback(err))
1631end)
1632success, result = pcall(function()
1633 return func(1, 2, 3)
1634end)
1635pcall(function()
1636 print("尝试中")
1637 return func(1, 2, 3)
1638end)
1639success, result = xpcall(function()
1640 return func(1, 2, 3)
1641end, function(err)
1642 return print(yue.traceback(err))
1643end)
1644if success then
1645 print(result)
1646end
1647local a, b, c
1648do
1649 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
1650 return func()
1651 end)
1652 if _ok_0 then
1653 a, b, c = _ret_0, _ret_1, _ret_2
1654 end
1655end
1656do
1657 local _exp_0 = ((function()
1658 return (function(_arg_0, ...)
1659 local _ok_0 = _arg_0
1660 if _ok_0 then
1661 return ...
1662 end
1663 end)(pcall(function()
1664 return func()
1665 end))
1666 end)())
1667 if _exp_0 ~= nil then
1668 a = _exp_0
1669 else
1670 a = "default"
1671 end
1672end
1673f((function()
1674 return (function(_arg_0, ...)
1675 local _ok_0 = _arg_0
1676 if _ok_0 then
1677 return ...
1678 end
1679 end)(pcall(function()
1680 return func()
1681 end))
1682end)())
1683f((function()
1684 return (function(_arg_0, ...)
1685 local _ok_0 = _arg_0
1686 if _ok_0 then
1687 return ...
1688 end
1689 end)(xpcall(function()
1690 print(123)
1691 return func()
1692 end, function(e)
1693 print(e)
1694 return e
1695 end))
1696end)())
1697local a <const> = 123
1698local _ <close> = setmetatable({ }, {
1699 __close = function()
1700 return print("超出范围。")
1701 end
1702})
1703local a, b, c, d
1704local _obj_0 = tb
1705a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
1706Constant = 123
849local a <const> = 123 1707local a <const> = 123
850local _ <close> = setmetatable({ }, { 1708local _ <close> = setmetatable({ }, {
851 __close = function() 1709 __close = function()
@@ -868,6 +1726,18 @@ fn = function()
868 return str 1726 return str
869end 1727end
870local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" 1728local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
1729local some_string = "这是一个字符串\n 并包括一个换行。"
1730print("我有" .. tostring(math.random() * 100) .. "%的把握。")
1731local integer = 1000000
1732local hex = 0xEFBBBF
1733local binary = 19
1734local str = "key: value\nlist:\n - item1\n - " .. tostring(expr)
1735local fn
1736fn = function()
1737 local str = "foo:\n bar: baz"
1738 return str
1739end
1740local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
871local my_function 1741local my_function
872my_function = function() end 1742my_function = function() end
873my_function() 1743my_function()
@@ -929,6 +1799,12 @@ some_args = function(x, y)
929 end 1799 end
930 return print(x + y) 1800 return print(x + y)
931end 1801end
1802local a = x - 10
1803local b = x - 10
1804local c = x(-y)
1805local d = x - z
1806local x = func("hello") + 100
1807local y = func("hello" + 100)
932my_func(5, 4, 3, 8, 9, 10) 1808my_func(5, 4, 3, 8, 9, 10)
933cool_func(1, 2, 3, 4, 5, 6, 7, 8) 1809cool_func(1, 2, 3, 4, 5, 6, 7, 8)
934my_func(5, 6, 7, 6, another_func(6, 7, 8, 9, 1, 2), 5, 4) 1810my_func(5, 6, 7, 6, another_func(6, 7, 8, 9, 1, 2), 5, 4)
@@ -1046,8 +1922,215 @@ process = function(...)
1046 return sum 1922 return sum
1047end 1923end
1048process(1, nil, 3, nil, 5) 1924process(1, nil, 3, nil, 5)
1049f(function() 1925local my_function
1050 return print("hello") 1926my_function = function() end
1927my_function()
1928local func_a
1929func_a = function()
1930 return print("你好,世界")
1931end
1932local func_b
1933func_b = function()
1934 local value = 100
1935 return print("这个值是:", value)
1936end
1937func_a()
1938func_b()
1939local sum
1940sum = function(x, y)
1941 return print("数字的和", x + y)
1942end
1943sum(10, 20)
1944print(sum(10, 20))
1945a(b(c("a", "b", "c")))
1946print("x:", sum(10, 20), "y:", sum(30, 40))
1947local sum
1948sum = function(x, y)
1949 return x + y
1950end
1951print("数字的和是", sum(10, 20))
1952local sum
1953sum = function(x, y)
1954 return x + y
1955end
1956local mystery
1957mystery = function(x, y)
1958 return x + y, x - y
1959end
1960local a, b = mystery(10, 20)
1961local func
1962func = function(self, num)
1963 return self.value + num
1964end
1965local my_function
1966my_function = function(name, height)
1967 if name == nil then
1968 name = "某物"
1969 end
1970 if height == nil then
1971 height = 100
1972 end
1973 print("你好,我是", name)
1974 return print("我的高度是", height)
1975end
1976local some_args
1977some_args = function(x, y)
1978 if x == nil then
1979 x = 100
1980 end
1981 if y == nil then
1982 y = x + 1000
1983 end
1984 return print(x + y)
1985end
1986local a = x - 10
1987local b = x - 10
1988local c = x(-y)
1989local d = x - z
1990local x = func("hello") + 100
1991local y = func("hello" + 100)
1992my_func(5, 4, 3, 8, 9, 10)
1993cool_func(1, 2, 3, 4, 5, 6, 7, 8)
1994my_func(5, 6, 7, 6, another_func(6, 7, 8, 9, 1, 2), 5, 4)
1995local x = {
1996 1,
1997 2,
1998 3,
1999 4,
2000 a_func(4, 5, 5, 6),
2001 8,
2002 9,
2003 10
2004}
2005local y = {
2006 my_func(1, 2, 3, 4, 5),
2007 5,
2008 6,
2009 7
2010}
2011if func(1, 2, 3, "你好", "世界") then
2012 print("你好")
2013 print("我在if内部")
2014end
2015if func(1, 2, 3, "你好", "世界") then
2016 print("你好")
2017 print("我在if内部")
2018end
2019local f1
2020f1 = function(_arg_0)
2021 local a, b, c
2022 a, b, c = _arg_0.a, _arg_0.b, _arg_0.c
2023 return print(a, b, c)
2024end
2025f1({
2026 a = 1,
2027 b = "2",
2028 c = { }
2029})
2030local f2
2031f2 = function(_arg_0, c)
2032 local a1, b
2033 a1, b = _arg_0.a, _arg_0.b
2034 if a1 == nil then
2035 a1 = 123
2036 end
2037 if b == nil then
2038 b = 'abc'
2039 end
2040 if c == nil then
2041 c = { }
2042 end
2043 return print(a1, b, c)
2044end
2045local arg1 = {
2046 a = 0
2047}
2048f2(arg1, arg2)
2049local findFirstEven
2050findFirstEven = function(list)
2051 for _index_0 = 1, #list do
2052 local item = list[_index_0]
2053 if type(item) == "table" then
2054 for _index_1 = 1, #item do
2055 local sub = item[_index_1]
2056 if sub % 2 == 0 then
2057 return sub
2058 end
2059 end
2060 end
2061 end
2062 return nil
2063end
2064local findFirstEven
2065findFirstEven = function(list)
2066 for _index_0 = 1, #list do
2067 local item = list[_index_0]
2068 if type(item) == "table" then
2069 for _index_1 = 1, #item do
2070 local sub = item[_index_1]
2071 if sub % 2 == 0 then
2072 return sub
2073 end
2074 end
2075 end
2076 end
2077 return nil
2078end
2079local f
2080f = function(...)
2081 local t = {
2082 n = select("#", ...),
2083 ...
2084 }
2085 print("参数个数:", t.n)
2086 print("表长度:", #t)
2087 for i = 1, t.n do
2088 print(t[i])
2089 end
2090end
2091f(1, 2, 3)
2092f("a", "b", "c", "d")
2093f()
2094local process
2095process = function(...)
2096 local args = {
2097 n = select("#", ...),
2098 ...
2099 }
2100 local sum = 0
2101 for i = 1, args.n do
2102 if args[i] ~= nil and type(args[i]) == "number" then
2103 sum = sum + args[i]
2104 end
2105 end
2106 return sum
2107end
2108process(1, nil, 3, nil, 5)
2109f(function(x)
2110 return print("hello" .. x)
2111end)
2112f(function(self)
2113 return print(self.value)
2114end)
2115map(function(x)
2116 return x * 2
2117end, {
2118 1,
2119 2,
2120 3
2121})
2122local result, msg
2123do
2124 result, msg = readAsync("文件名.txt", function(data)
2125 print(data)
2126 return processAsync(data, function(info)
2127 return check(info)
2128 end)
2129 end)
2130end
2131print(result, msg)
2132f(function(x)
2133 return print("hello" .. x)
1051end) 2134end)
1052f(function(self) 2135f(function(self)
1053 return print(self.value) 2136 return print(self.value)
@@ -1137,6 +2220,74 @@ local some_values = {
1137local list_with_one_element = { 2220local list_with_one_element = {
1138 1 2221 1
1139} 2222}
2223local some_values = {
2224 1,
2225 2,
2226 3,
2227 4
2228}
2229local some_values = {
2230 name = "Bill",
2231 age = 200,
2232 ["favorite food"] = "rice"
2233}
2234local profile = {
2235 height = "4英尺",
2236 shoe_size = 13,
2237 favorite_foods = {
2238 "冰淇淋",
2239 "甜甜圈"
2240 }
2241}
2242local values = {
2243 1,
2244 2,
2245 3,
2246 4,
2247 5,
2248 6,
2249 7,
2250 8,
2251 name = "超人",
2252 occupation = "打击犯罪"
2253}
2254my_function({
2255 dance = "探戈",
2256 partner = "无"
2257})
2258local y = {
2259 type = "狗",
2260 legs = 4,
2261 tails = 1
2262}
2263local tbl = {
2264 ["do"] = "某事",
2265 ["end"] = "饥饿"
2266}
2267local hair = "金色"
2268local height = 200
2269local person = {
2270 hair = hair,
2271 height = height,
2272 shoe_size = 40
2273}
2274print_table({
2275 hair = hair,
2276 height = height
2277})
2278local t = {
2279 [1 + 2] = "你好",
2280 ["你好 世界"] = true
2281}
2282local some_values = {
2283 1,
2284 2,
2285 3,
2286 4
2287}
2288local list_with_one_element = {
2289 1
2290}
1140local items = { 2291local items = {
1141 1, 2292 1,
1142 2, 2293 2,
@@ -1335,15 +2486,250 @@ for _index_0 = _min_0, 1, -1 do
1335end 2486end
1336reverse_slice = _accum_0 2487reverse_slice = _accum_0
1337local sub_list 2488local sub_list
2489do
2490 local _accum_0 = { }
2491 local _len_0 = 1
2492 local _list_0 = items
2493 for _index_0 = 2, 4 do
2494 local _item_0 = _list_0[_index_0]
2495 _accum_0[_len_0] = _item_0
2496 _len_0 = _len_0 + 1
2497 end
2498 sub_list = _accum_0
2499end
2500local last_four_items
1338local _accum_0 = { } 2501local _accum_0 = { }
1339local _len_0 = 1 2502local _len_0 = 1
1340local _list_0 = items 2503local _list_0 = items
1341for _index_0 = 2, 4 do 2504local _min_0 = #_list_0 + -4 + 1
2505local _max_0 = #_list_0 + -1 + 1
2506for _index_0 = _min_0, _max_0 do
2507 local _item_0 = _list_0[_index_0]
2508 _accum_0[_len_0] = _item_0
2509 _len_0 = _len_0 + 1
2510end
2511last_four_items = _accum_0
2512local items = {
2513 1,
2514 2,
2515 3,
2516 4
2517}
2518local doubled
2519local _accum_0 = { }
2520local _len_0 = 1
2521for i, item in ipairs(items) do
2522 _accum_0[_len_0] = item * 2
2523 _len_0 = _len_0 + 1
2524end
2525doubled = _accum_0
2526local slice
2527local _accum_0 = { }
2528local _len_0 = 1
2529for i, item in ipairs(items) do
2530 if i > 1 and i < 3 then
2531 _accum_0[_len_0] = item
2532 _len_0 = _len_0 + 1
2533 end
2534end
2535slice = _accum_0
2536local doubled
2537local _accum_0 = { }
2538local _len_0 = 1
2539local _list_0 = items
2540for _index_0 = 1, #_list_0 do
2541 local item = _list_0[_index_0]
2542 _accum_0[_len_0] = item * 2
2543 _len_0 = _len_0 + 1
2544end
2545doubled = _accum_0
2546local data = {
2547 a = {
2548 1,
2549 2,
2550 3
2551 },
2552 b = {
2553 4,
2554 5,
2555 6
2556 }
2557}
2558local flat
2559local _accum_0 = { }
2560for k, v in pairs(data) do
2561 local _len_0 = #_accum_0 + 1
2562 for _index_0 = 1, #v do
2563 local _elm_0 = v[_index_0]
2564 _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1
2565 end
2566end
2567flat = _accum_0
2568local x_coords = {
2569 4,
2570 5,
2571 6,
2572 7
2573}
2574local y_coords = {
2575 9,
2576 2,
2577 3
2578}
2579local points
2580local _accum_0 = { }
2581local _len_0 = 1
2582for _index_0 = 1, #x_coords do
2583 local x = x_coords[_index_0]
2584 for _index_1 = 1, #y_coords do
2585 local y = y_coords[_index_1]
2586 _accum_0[_len_0] = {
2587 x,
2588 y
2589 }
2590 _len_0 = _len_0 + 1
2591 end
2592end
2593points = _accum_0
2594local evens
2595local _accum_0 = { }
2596local _len_0 = 1
2597for i = 1, 100 do
2598 if i % 2 == 0 then
2599 _accum_0[_len_0] = i
2600 _len_0 = _len_0 + 1
2601 end
2602end
2603evens = _accum_0
2604local thing = {
2605 color = "red",
2606 name = "fast",
2607 width = 123
2608}
2609local thing_copy
2610local _tbl_0 = { }
2611for k, v in pairs(thing) do
2612 _tbl_0[k] = v
2613end
2614thing_copy = _tbl_0
2615local no_color
2616local _tbl_0 = { }
2617for k, v in pairs(thing) do
2618 if k ~= "color" then
2619 _tbl_0[k] = v
2620 end
2621end
2622no_color = _tbl_0
2623local numbers = {
2624 1,
2625 2,
2626 3,
2627 4
2628}
2629local sqrts
2630local _tbl_0 = { }
2631for _index_0 = 1, #numbers do
2632 local i = numbers[_index_0]
2633 _tbl_0[i] = math.sqrt(i)
2634end
2635sqrts = _tbl_0
2636local tuples = {
2637 {
2638 "hello",
2639 "world"
2640 },
2641 {
2642 "foo",
2643 "bar"
2644 }
2645}
2646local tbl
2647local _tbl_0 = { }
2648for _index_0 = 1, #tuples do
2649 local tuple = tuples[_index_0]
2650 local _key_0, _val_0 = unpack(tuple)
2651 _tbl_0[_key_0] = _val_0
2652end
2653tbl = _tbl_0
2654local slice
2655local _accum_0 = { }
2656local _len_0 = 1
2657local _list_0 = items
2658for _index_0 = 1, 5 do
2659 local item = _list_0[_index_0]
2660 _accum_0[_len_0] = item
2661 _len_0 = _len_0 + 1
2662end
2663slice = _accum_0
2664local slice
2665local _accum_0 = { }
2666local _len_0 = 1
2667local _list_0 = items
2668local _max_0 = #_list_0
2669for _index_0 = 2, _max_0 do
2670 local item = _list_0[_index_0]
2671 _accum_0[_len_0] = item
2672 _len_0 = _len_0 + 1
2673end
2674slice = _accum_0
2675local slice
2676local _accum_0 = { }
2677local _len_0 = 1
2678local _list_0 = items
2679local _max_0 = #_list_0
2680for _index_0 = 1, _max_0, 2 do
2681 local item = _list_0[_index_0]
2682 _accum_0[_len_0] = item
2683 _len_0 = _len_0 + 1
2684end
2685slice = _accum_0
2686local slice
2687local _accum_0 = { }
2688local _len_0 = 1
2689local _list_0 = items
2690local _min_0 = #_list_0 + -4 + 1
2691local _max_0 = #_list_0 + -1 + 1
2692for _index_0 = _min_0, _max_0 do
2693 local item = _list_0[_index_0]
2694 _accum_0[_len_0] = item
2695 _len_0 = _len_0 + 1
2696end
2697slice = _accum_0
2698local reverse_slice
2699local _accum_0 = { }
2700local _len_0 = 1
2701local _list_0 = items
2702local _min_0 = #_list_0 + -1 + 1
2703for _index_0 = _min_0, 1, -1 do
2704 local item = _list_0[_index_0]
2705 _accum_0[_len_0] = item
2706 _len_0 = _len_0 + 1
2707end
2708reverse_slice = _accum_0
2709local sub_list
2710do
2711 local _accum_0 = { }
2712 local _len_0 = 1
2713 local _list_0 = items
2714 for _index_0 = 2, 4 do
2715 local _item_0 = _list_0[_index_0]
2716 _accum_0[_len_0] = _item_0
2717 _len_0 = _len_0 + 1
2718 end
2719 sub_list = _accum_0
2720end
2721local last_four_items
2722local _accum_0 = { }
2723local _len_0 = 1
2724local _list_0 = items
2725local _min_0 = #_list_0 + -4 + 1
2726local _max_0 = #_list_0 + -1 + 1
2727for _index_0 = _min_0, _max_0 do
1342 local _item_0 = _list_0[_index_0] 2728 local _item_0 = _list_0[_index_0]
1343 _accum_0[_len_0] = _item_0 2729 _accum_0[_len_0] = _item_0
1344 _len_0 = _len_0 + 1 2730 _len_0 = _len_0 + 1
1345end 2731end
1346sub_list = _accum_0 2732last_four_items = _accum_0
1347for i = 10, 20 do 2733for i = 10, 20 do
1348 print(i) 2734 print(i)
1349end 2735end
@@ -1408,6 +2794,86 @@ func_b = function()
1408end 2794end
1409print(func_a()) 2795print(func_a())
1410print(func_b()) 2796print(func_b())
2797for i = 10, 20 do
2798 print(i)
2799end
2800for k = 1, 15, 2 do
2801 print(k)
2802end
2803for key, value in pairs(object) do
2804 print(key, value)
2805end
2806local _list_0 = items
2807for _index_0 = 2, 4 do
2808 local item = _list_0[_index_0]
2809 print(item)
2810end
2811local _list_0 = items
2812for _index_0 = 1, #_list_0 do
2813 local item = _list_0[_index_0]
2814 print(item)
2815end
2816for j = 1, 10, 3 do
2817 print(j)
2818end
2819local doubled_evens
2820local _accum_0 = { }
2821local _len_0 = 1
2822for i = 1, 20 do
2823 if i % 2 == 0 then
2824 _accum_0[_len_0] = i * 2
2825 _len_0 = _len_0 + 1
2826 else
2827 _accum_0[_len_0] = i
2828 _len_0 = _len_0 + 1
2829 end
2830end
2831doubled_evens = _accum_0
2832local first_large
2833local _accum_0
2834local _list_0 = numbers
2835for _index_0 = 1, #_list_0 do
2836 local n = _list_0[_index_0]
2837 if n > 10 then
2838 _accum_0 = n
2839 break
2840 end
2841end
2842first_large = _accum_0
2843local func_a
2844func_a = function()
2845 for i = 1, 10 do
2846 print(i)
2847 end
2848end
2849local func_b
2850func_b = function()
2851 local _accum_0 = { }
2852 local _len_0 = 1
2853 for i = 1, 10 do
2854 _accum_0[_len_0] = i
2855 _len_0 = _len_0 + 1
2856 end
2857 return _accum_0
2858end
2859print(func_a())
2860print(func_b())
2861local i = 10
2862while i > 0 do
2863 print(i)
2864 i = i - 1
2865end
2866while running == true do
2867 my_function()
2868end
2869local i = 10
2870while not (i == 0) do
2871 print(i)
2872 i = i - 1
2873end
2874while not (running == false) do
2875 my_function()
2876end
1411local i = 10 2877local i = 10
1412repeat 2878repeat
1413 print(i) 2879 print(i)
@@ -1429,6 +2895,11 @@ end
1429while not (running == false) do 2895while not (running == false) do
1430 my_function() 2896 my_function()
1431end 2897end
2898local i = 10
2899repeat
2900 print(i)
2901 i = i - 1
2902until i == 0
1432local i = 0 2903local i = 0
1433while i < 10 do 2904while i < 10 do
1434 i = i + 1 2905 i = i + 1
@@ -1459,6 +2930,95 @@ for _index_0 = 1, #my_numbers do
1459 ::_continue_0:: 2930 ::_continue_0::
1460end 2931end
1461odds = _accum_0 2932odds = _accum_0
2933local i = 0
2934while i < 10 do
2935 i = i + 1
2936 if i % 2 == 0 then
2937 goto _continue_0
2938 end
2939 print(i)
2940 ::_continue_0::
2941end
2942local my_numbers = {
2943 1,
2944 2,
2945 3,
2946 4,
2947 5,
2948 6
2949}
2950local odds
2951local _accum_0 = { }
2952local _len_0 = 1
2953for _index_0 = 1, #my_numbers do
2954 local x = my_numbers[_index_0]
2955 if x % 2 == 1 then
2956 goto _continue_0
2957 end
2958 _accum_0[_len_0] = x
2959 _len_0 = _len_0 + 1
2960 ::_continue_0::
2961end
2962odds = _accum_0
2963local have_coins = false
2964if have_coins then
2965 print("有硬币")
2966else
2967 print("没有硬币")
2968end
2969local have_coins = false
2970if have_coins then
2971 print("有硬币")
2972else
2973 print("没有硬币")
2974end
2975local have_coins = false
2976print((function()
2977 if have_coins then
2978 return "有硬币"
2979 else
2980 return "没有硬币"
2981 end
2982end)())
2983local is_tall
2984is_tall = function(name)
2985 if name == "Rob" then
2986 return true
2987 else
2988 return false
2989 end
2990end
2991local message
2992if is_tall("Rob") then
2993 message = "我很高"
2994else
2995 message = "我不是很高"
2996end
2997print(message)
2998if not (os.date("%A") == "Monday") then
2999 print("今天不是星期一!")
3000end
3001if not (math.random() > 0.1) then
3002 print("你真幸运!")
3003end
3004local a = 5
3005if (1 == a or 3 == a or 5 == a or 7 == a) then
3006 print("检查离散值的相等性")
3007end
3008if (function()
3009 local _check_0 = list
3010 for _index_0 = 1, #_check_0 do
3011 if _check_0[_index_0] == a then
3012 return true
3013 end
3014 end
3015 return false
3016end)() then
3017 print("检查`a`是否在列表中")
3018end
3019if not (math.random() > 0.1) then
3020 print("你很幸运!")
3021end
1462local have_coins = false 3022local have_coins = false
1463if have_coins then 3023if have_coins then
1464 print("有硬币") 3024 print("有硬币")
@@ -1532,6 +3092,312 @@ end
1532while not reader:eof() do 3092while not reader:eof() do
1533 reader:parse_line() 3093 reader:parse_line()
1534end 3094end
3095if name == "Rob" then
3096 print("你好,世界")
3097end
3098local _list_0 = items
3099for _index_0 = 1, #_list_0 do
3100 local item = _list_0[_index_0]
3101 print("项目: ", item)
3102end
3103while game:isRunning() do
3104 game:update()
3105end
3106while not reader:eof() do
3107 reader:parse_line()
3108end
3109local name = "Dan"
3110if "Robert" == name then
3111 print("你是Robert")
3112elseif "Dan" == name or "Daniel" == name then
3113 print("你的名字是Dan")
3114else
3115 print("我不认识你,你的名字是" .. tostring(name))
3116end
3117local b = 1
3118local next_number
3119if 1 == b then
3120 next_number = 2
3121elseif 2 == b then
3122 next_number = 3
3123else
3124 next_number = error("数字数得太大了!")
3125end
3126local msg
3127local _exp_0 = math.random(1, 5)
3128if 1 == _exp_0 then
3129 msg = "你很幸运"
3130elseif 2 == _exp_0 then
3131 msg = "你差点很幸运"
3132else
3133 msg = "不太幸运"
3134end
3135do
3136 local _exp_0 = math.random(1, 5)
3137 if 1 == _exp_0 then
3138 print("你很幸运")
3139 else
3140 print("不太幸运")
3141 end
3142end
3143local _exp_0 = math.random(1, 5)
3144if 1 == _exp_0 then
3145 print("你很幸运")
3146else
3147 print("不太幸运")
3148end
3149local items = {
3150 {
3151 x = 100,
3152 y = 200
3153 },
3154 {
3155 width = 300,
3156 height = 400
3157 }
3158}
3159for _index_0 = 1, #items do
3160 local item = items[_index_0]
3161 local _type_0 = type(item)
3162 local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3163 local _match_0 = false
3164 if _tab_0 then
3165 local x = item.x
3166 local y = item.y
3167 if x ~= nil and y ~= nil then
3168 _match_0 = true
3169 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
3170 end
3171 end
3172 if not _match_0 then
3173 if _tab_0 then
3174 local width = item.width
3175 local height = item.height
3176 if width ~= nil and height ~= nil then
3177 print("尺寸 " .. tostring(width) .. ", " .. tostring(height))
3178 end
3179 end
3180 end
3181end
3182local item = { }
3183local x, y = item.pos.x, item.pos.y
3184if x == nil then
3185 x = 50
3186end
3187if y == nil then
3188 y = 200
3189end
3190local _type_0 = type(item)
3191local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3192if _tab_0 then
3193 do
3194 local _obj_0 = item.pos
3195 local _type_1 = type(_obj_0)
3196 if "table" == _type_1 or "userdata" == _type_1 then
3197 x = _obj_0.x
3198 end
3199 end
3200 do
3201 local _obj_0 = item.pos
3202 local _type_1 = type(_obj_0)
3203 if "table" == _type_1 or "userdata" == _type_1 then
3204 y = _obj_0.y
3205 end
3206 end
3207 if x == nil then
3208 x = 50
3209 end
3210 if y == nil then
3211 y = 200
3212 end
3213 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
3214end
3215local _exp_0 = tb
3216local _type_0 = type(_exp_0)
3217local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3218local _match_0 = false
3219if _tab_0 then
3220 if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then
3221 _match_0 = true
3222 print("1, 2, 3")
3223 end
3224end
3225if not _match_0 then
3226 local _match_1 = false
3227 if _tab_0 then
3228 local b = _exp_0[2]
3229 if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then
3230 _match_1 = true
3231 print("1, " .. tostring(b) .. ", 3")
3232 end
3233 end
3234 if not _match_1 then
3235 if _tab_0 then
3236 local b = _exp_0[3]
3237 if b == nil then
3238 b = 3
3239 end
3240 if 1 == _exp_0[1] and 2 == _exp_0[2] then
3241 print("1, 2, " .. tostring(b))
3242 end
3243 end
3244 end
3245end
3246local _exp_0 = tb
3247local _type_0 = type(_exp_0)
3248local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3249local _match_0 = false
3250if _tab_0 then
3251 local result = _exp_0.result
3252 if true == _exp_0.success and result ~= nil then
3253 _match_0 = true
3254 print("成功", result)
3255 end
3256end
3257if not _match_0 then
3258 local _match_1 = false
3259 if _tab_0 then
3260 if false == _exp_0.success then
3261 _match_1 = true
3262 print("失败", result)
3263 end
3264 end
3265 if not _match_1 then
3266 print("无效值")
3267 end
3268end
3269local _exp_0 = tb
3270local _type_0 = type(_exp_0)
3271local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3272local _match_0 = false
3273if _tab_0 then
3274 local content
3275 do
3276 local _obj_0 = _exp_0.data
3277 local _type_1 = type(_obj_0)
3278 if "table" == _type_1 or "userdata" == _type_1 then
3279 content = _obj_0.content
3280 end
3281 end
3282 local _val_0
3283 do
3284 local _obj_0 = _exp_0.data
3285 if _obj_0 ~= nil then
3286 _val_0 = _obj_0.type
3287 end
3288 end
3289 if "success" == _val_0 and content ~= nil then
3290 _match_0 = true
3291 print("成功", content)
3292 end
3293end
3294if not _match_0 then
3295 local _match_1 = false
3296 if _tab_0 then
3297 local content
3298 do
3299 local _obj_0 = _exp_0.data
3300 local _type_1 = type(_obj_0)
3301 if "table" == _type_1 or "userdata" == _type_1 then
3302 content = _obj_0.content
3303 end
3304 end
3305 local _val_0
3306 do
3307 local _obj_0 = _exp_0.data
3308 if _obj_0 ~= nil then
3309 _val_0 = _obj_0.type
3310 end
3311 end
3312 if "error" == _val_0 and content ~= nil then
3313 _match_1 = true
3314 print("失败", content)
3315 end
3316 end
3317 if not _match_1 then
3318 print("无效值")
3319 end
3320end
3321local _exp_0 = tb
3322local _type_0 = type(_exp_0)
3323local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3324if _tab_0 then
3325 local fourth = _exp_0[4]
3326 local _val_0
3327 do
3328 local _obj_0 = _exp_0[1]
3329 if _obj_0 ~= nil then
3330 _val_0 = _obj_0.a
3331 end
3332 end
3333 local _val_1
3334 do
3335 local _obj_0 = _exp_0[1]
3336 if _obj_0 ~= nil then
3337 _val_1 = _obj_0.b
3338 end
3339 end
3340 local _val_2
3341 do
3342 local _obj_0 = _exp_0[2]
3343 if _obj_0 ~= nil then
3344 _val_2 = _obj_0.a
3345 end
3346 end
3347 local _val_3
3348 do
3349 local _obj_0 = _exp_0[2]
3350 if _obj_0 ~= nil then
3351 _val_3 = _obj_0.b
3352 end
3353 end
3354 local _val_4
3355 do
3356 local _obj_0 = _exp_0[3]
3357 if _obj_0 ~= nil then
3358 _val_4 = _obj_0.a
3359 end
3360 end
3361 local _val_5
3362 do
3363 local _obj_0 = _exp_0[3]
3364 if _obj_0 ~= nil then
3365 _val_5 = _obj_0.b
3366 end
3367 end
3368 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
3369 print("匹配成功", fourth)
3370 end
3371end
3372local segments = {
3373 "admin",
3374 "users",
3375 "logs",
3376 "view"
3377}
3378local _type_0 = type(segments)
3379local _tab_0 = "table" == _type_0 or "userdata" == _type_0
3380if _tab_0 then
3381 local groups
3382 do
3383 local _accum_0 = { }
3384 local _len_0 = 1
3385 local _max_0 = #segments + -3 + 1
3386 for _index_0 = 1, _max_0 do
3387 local _item_0 = segments[_index_0]
3388 _accum_0[_len_0] = _item_0
3389 _len_0 = _len_0 + 1
3390 end
3391 groups = _accum_0
3392 end
3393 local resource = segments[#segments - 1]
3394 local action = segments[#segments]
3395 if resource ~= nil and action ~= nil then
3396 print("Group:", groups)
3397 print("Resource:", resource)
3398 print("Action:", action)
3399 end
3400end
1535local name = "Dan" 3401local name = "Dan"
1536if "Robert" == name then 3402if "Robert" == name then
1537 print("你是Robert") 3403 print("你是Robert")
@@ -2444,1940 +4310,6 @@ end
2444local y = Y() 4310local y = Y()
2445y:func() 4311y:func()
2446assert(y.__class.__parent ~= X) 4312assert(y.__class.__parent ~= X)
2447local _with_0 = Person()
2448_with_0.name = "Oswald"
2449_with_0:add_relative(my_dad)
2450_with_0:save()
2451print(_with_0.name)
2452local file
2453local _with_0 = File("favorite_foods.txt")
2454_with_0:set_encoding("utf8")
2455file = _with_0
2456local create_person
2457create_person = function(name, relatives)
2458 local _with_0 = Person()
2459 _with_0.name = name
2460 for _index_0 = 1, #relatives do
2461 local relative = relatives[_index_0]
2462 _with_0:add_relative(relative)
2463 end
2464 return _with_0
2465end
2466local me = create_person("Leaf", {
2467 dad,
2468 mother,
2469 sister
2470})
2471local str = "你好"
2472print("原始:", str)
2473print("大写:", str:upper())
2474local _with_0 = tb
2475_with_0[1] = 1
2476print(_with_0[2])
2477do
2478 local _with_1 = _with_0[abc]
2479 _with_1[3] = _with_1[2]:func()
2480 _with_1["key-name"] = value
2481end
2482_with_0[#_with_0 + 1] = "abc"
2483local _with_0 = obj
2484if _with_0 ~= nil then
2485 print(obj.name)
2486end
2487do
2488 local var = "hello"
2489 print(var)
2490end
2491print(var)
2492local counter
2493do
2494 local i = 0
2495 counter = function()
2496 i = i + 1
2497 return i
2498 end
2499end
2500print(counter())
2501print(counter())
2502local tbl = {
2503 key = (function()
2504 print("分配键值!")
2505 return 1234
2506 end)()
2507}
2508local my_object = {
2509 value = 1000,
2510 write = function(self)
2511 return print("值为:", self.value)
2512 end
2513}
2514local run_callback
2515run_callback = function(func)
2516 print("运行回调...")
2517 return func()
2518end
2519run_callback(my_object.write)
2520run_callback((function()
2521 local _base_0 = my_object
2522 local _fn_0 = _base_0.write
2523 return _fn_0 and function(...)
2524 return _fn_0(_base_0, ...)
2525 end
2526end)())
2527local i = 100
2528local my_func
2529my_func = function()
2530 i = 10
2531 while i > 0 do
2532 print(i)
2533 i = i - 1
2534 end
2535end
2536my_func()
2537print(i)
2538local i = 100
2539local my_func
2540my_func = function()
2541 local i = "hello"
2542end
2543my_func()
2544print(i)
2545local tmp = 1213
2546local i, k = 100, 50
2547local my_func
2548my_func = function(add)
2549 local tmp = tmp + add
2550 i = i + tmp
2551 k = k + tmp
2552end
2553my_func(22)
2554print(i, k)
2555local _module_0 = { }
2556local p, to_lua
2557do
2558 local _obj_0 = require("yue")
2559 p, to_lua = _obj_0.p, _obj_0.to_lua
2560end
2561local inventory = {
2562 equipment = {
2563 "sword",
2564 "shield"
2565 },
2566 items = {
2567 {
2568 name = "potion",
2569 count = 10
2570 },
2571 {
2572 name = "bread",
2573 count = 3
2574 }
2575 }
2576}
2577local map
2578map = function(arr, action)
2579 local _accum_0 = { }
2580 local _len_0 = 1
2581 for _index_0 = 1, #arr do
2582 local item = arr[_index_0]
2583 _accum_0[_len_0] = action(item)
2584 _len_0 = _len_0 + 1
2585 end
2586 return _accum_0
2587end
2588local filter
2589filter = function(arr, cond)
2590 local _accum_0 = { }
2591 local _len_0 = 1
2592 for _index_0 = 1, #arr do
2593 local item = arr[_index_0]
2594 if cond(item) then
2595 _accum_0[_len_0] = item
2596 _len_0 = _len_0 + 1
2597 end
2598 end
2599 return _accum_0
2600end
2601local reduce
2602reduce = function(arr, init, action)
2603 for _index_0 = 1, #arr do
2604 local item = arr[_index_0]
2605 init = action(init, item)
2606 end
2607 return init
2608end
2609print(reduce(filter(map({
2610 1,
2611 2,
2612 3
2613}, function(x)
2614 return x * 2
2615end), function(x)
2616 return x > 4
2617end), 0, function(a, b)
2618 return a + b
2619end))
2620local apple = setmetatable({
2621 size = 15,
2622}, {
2623 __index = {
2624 color = 0x00ffff
2625 }
2626})
2627if (getmetatable(apple) ~= nil) then
2628 p(apple.size, apple.color, getmetatable(apple).__index)
2629end
2630local _u1f31b = "月之脚本"
2631_module_0["🌛"] = _u1f31b
2632return _module_0
2633local area = 6.2831853071796 * 5
2634print('你好 世界')
2635do
2636 assert(item ~= nil)
2637end
2638local value = item
2639if (f1() and f2() and f3()) then
2640 print("OK")
2641end
2642do
2643 local funcA
2644 funcA = function() end
2645end
2646local funcA
2647funcA = function()
2648 return "无法访问宏生成月之脚本里定义的变量"
2649end
2650do
2651local function funcB() end
2652end
2653local funcB
2654funcB = function()
2655 return "无法访问宏生成 Lua 代码里定义的变量"
2656end
2657do
2658-- 插入原始Lua代码
2659if cond then
2660 print("输出")
2661end
2662end
2663print("yuescript")
2664print(2)
2665print("有效的枚举类型:", "Static")
2666do
2667 print(123, "hello")
2668end
2669do
2670 print(123, "hello")
2671end
2672if tb ~= nil then
2673 tb:func()
2674end
2675if tb ~= nil then
2676 tb:func()
2677end
2678print(1 < 2 and 2 <= 2 and 2 < 3 and 3 == 3 and 3 > 2 and 2 >= 1 and 1 == 1 and 1 < 3 and 3 ~= 5)
2679local a = 5
2680print(1 <= a and a <= 10)
2681local v
2682v = function(x)
2683 print(x)
2684 return x
2685end
2686print((function()
2687 local _cond_0 = v(2)
2688 if not (v(1) < _cond_0) then
2689 return false
2690 else
2691 return _cond_0 <= v(3)
2692 end
2693end)())
2694print((function()
2695 local _cond_0 = v(2)
2696 if not (v(1) > _cond_0) then
2697 return false
2698 else
2699 return _cond_0 <= v(3)
2700 end
2701end)())
2702local tab = { }
2703tab[#tab + 1] = "Value"
2704local tbA = {
2705 1,
2706 2,
2707 3
2708}
2709local tbB = {
2710 4,
2711 5,
2712 6
2713}
2714local _len_0 = #tbA + 1
2715for _index_0 = 1, #tbB do
2716 local _elm_0 = tbB[_index_0]
2717 tbA[_len_0], _len_0 = _elm_0, _len_0 + 1
2718end
2719local parts = {
2720 "shoulders",
2721 "knees"
2722}
2723local lyrics
2724do
2725 local _tab_0 = {
2726 "head"
2727 }
2728 local _idx_0 = 1
2729 for _key_0, _value_0 in pairs(parts) do
2730 if _idx_0 == _key_0 then
2731 _tab_0[#_tab_0 + 1] = _value_0
2732 _idx_0 = _idx_0 + 1
2733 else
2734 _tab_0[_key_0] = _value_0
2735 end
2736 end
2737 _tab_0[#_tab_0 + 1] = "and"
2738 _tab_0[#_tab_0 + 1] = "toes"
2739 lyrics = _tab_0
2740end
2741local copy
2742do
2743 local _tab_0 = { }
2744 local _idx_0 = 1
2745 for _key_0, _value_0 in pairs(other) do
2746 if _idx_0 == _key_0 then
2747 _tab_0[#_tab_0 + 1] = _value_0
2748 _idx_0 = _idx_0 + 1
2749 else
2750 _tab_0[_key_0] = _value_0
2751 end
2752 end
2753 copy = _tab_0
2754end
2755local a = {
2756 1,
2757 2,
2758 3,
2759 x = 1
2760}
2761local b = {
2762 4,
2763 5,
2764 y = 1
2765}
2766local merge
2767local _tab_0 = { }
2768local _idx_0 = 1
2769for _key_0, _value_0 in pairs(a) do
2770 if _idx_0 == _key_0 then
2771 _tab_0[#_tab_0 + 1] = _value_0
2772 _idx_0 = _idx_0 + 1
2773 else
2774 _tab_0[_key_0] = _value_0
2775 end
2776end
2777local _idx_1 = 1
2778for _key_0, _value_0 in pairs(b) do
2779 if _idx_1 == _key_0 then
2780 _tab_0[#_tab_0 + 1] = _value_0
2781 _idx_1 = _idx_1 + 1
2782 else
2783 _tab_0[_key_0] = _value_0
2784 end
2785end
2786merge = _tab_0
2787local last
2788do
2789 local _item_0 = data.items
2790 last = _item_0[#_item_0]
2791end
2792local second_last
2793do
2794 local _item_0 = data.items
2795 second_last = _item_0[#_item_0 - 1]
2796end
2797local _obj_0 = data.items
2798_obj_0[#_obj_0] = 1
2799local mt = { }
2800local add
2801add = function(self, right)
2802 return setmetatable({
2803 value = self.value + right.value
2804 }, mt)
2805end
2806mt.__add = add
2807local a = setmetatable({
2808 value = 1
2809}, mt)
2810local b = setmetatable({
2811 value = 2
2812}, {
2813 __add = add
2814})
2815local c = setmetatable({
2816 value = 3
2817}, {
2818 __add = mt.__add
2819})
2820local d = a + b + c
2821print(d.value)
2822local _ <close> = setmetatable({ }, {
2823 __close = function()
2824 return print("超出范围")
2825 end
2826})
2827local tb = setmetatable({ }, {
2828 ["value"] = 123
2829})
2830getmetatable(tb).__index = getmetatable(tb)
2831print(tb.value)
2832setmetatable(tb, {
2833 __index = {
2834 item = "hello"
2835 }
2836})
2837print(tb.item)
2838local item, new, close, getter
2839do
2840 local _obj_0 = tb
2841 item, new = _obj_0[1], _obj_0.new
2842 do
2843 local _obj_1 = getmetatable(_obj_0)
2844 close, getter = _obj_1.__close, _obj_1.__index
2845 end
2846end
2847print(item, new, close, getter)
2848do
2849 local _obj_0 = func
2850 if _obj_0 ~= nil then
2851 _obj_0()
2852 end
2853end
2854print((function()
2855 local _obj_0 = abc
2856 if _obj_0 ~= nil then
2857 local _obj_1 = _obj_0["你好 世界"]
2858 if _obj_1 ~= nil then
2859 return _obj_1.xyz
2860 end
2861 return nil
2862 end
2863 return nil
2864end)())
2865local x
2866do
2867 local _obj_0 = tab
2868 if _obj_0 ~= nil then
2869 x = _obj_0.value
2870 end
2871end
2872local len = (function()
2873 local _obj_0 = utf8
2874 if _obj_0 ~= nil then
2875 return _obj_0.len
2876 end
2877 return nil
2878end)() or (function()
2879 local _obj_0 = string
2880 if _obj_0 ~= nil then
2881 return _obj_0.len
2882 end
2883 return nil
2884end)() or function(o)
2885 return #o
2886end
2887if print and (x ~= nil) then
2888 print(x)
2889end
2890local _with_0 = io.open("test.txt", "w")
2891if _with_0 ~= nil then
2892 _with_0:write("你好")
2893 _with_0:close()
2894end
2895print("你好")
2896print(1, 2)
2897print(1, 2, 3)
2898print(render(emit(parse(extract(readFile("example.txt"), language, { }), language))))
2899local a, b, c, d
2900if b ~= nil then
2901 a = b
2902else
2903 if c ~= nil then
2904 a = c
2905 else
2906 a = d
2907 end
2908end
2909func((function()
2910 if a ~= nil then
2911 return a
2912 else
2913 return { }
2914 end
2915end)())
2916if a == nil then
2917 a = false
2918end
2919local list = {
2920 1,
2921 2,
2922 3
2923}
2924func({
2925 1,
2926 2,
2927 3
2928})
2929local f
2930f = function()
2931 return {
2932 1,
2933 2,
2934 3
2935 }
2936end
2937local tb = {
2938 name = "abc",
2939 values = {
2940 "a",
2941 "b",
2942 "c"
2943 },
2944 objects = {
2945 {
2946 name = "a",
2947 value = 1,
2948 func = function(self)
2949 return self.value + 1
2950 end,
2951 tb = {
2952 fieldA = 1
2953 }
2954 },
2955 {
2956 name = "b",
2957 value = 2,
2958 func = function(self)
2959 return self.value + 2
2960 end,
2961 tb = { }
2962 }
2963 }
2964}
2965do
2966 local insert, concat = table.insert, table.concat
2967 local C, Ct, Cmt
2968 do
2969 local _obj_0 = require("lpeg")
2970 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
2971 end
2972 local x, y, z
2973 do
2974 local _obj_0 = require('mymodule')
2975 x, y, z = _obj_0.x, _obj_0.y, _obj_0.z
2976 end
2977 local a, b, c
2978 local _obj_0 = require('module')
2979 a, b, c = _obj_0.a, _obj_0.b, _obj_0.c
2980end
2981do
2982 local module = require('module')
2983 local module_x = require('module_x')
2984 local d_a_s_h_e_s = require("d-a-s-h-e-s")
2985 local part = require("module.part")
2986end
2987do
2988 local PlayerModule = require("player")
2989 local C, Ct, Cmt
2990 do
2991 local _obj_0 = require("lpeg")
2992 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
2993 end
2994 local one, two, ch
2995 local _obj_0 = require("export")
2996 one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1]
2997end
2998do
2999 local tostring <const> = tostring
3000 local concat <const> = table.concat
3001 print(concat({
3002 "a",
3003 tostring(1)
3004 }))
3005end
3006do
3007 local print <const> = print
3008 local math <const> = math
3009 print("hello")
3010 math.random(3)
3011end
3012do
3013 local print <const> = print
3014 print(FLAG)
3015 FLAG = 123
3016end
3017local _module_0 = { }
3018local a, b, c = 1, 2, 3
3019_module_0["a"], _module_0["b"], _module_0["c"] = a, b, c
3020local cool = "cat"
3021_module_0["cool"] = cool
3022local What
3023if this then
3024 What = "abc"
3025else
3026 What = "def"
3027end
3028_module_0["What"] = What
3029local y
3030y = function()
3031 local hallo = 3434
3032end
3033_module_0["y"] = y
3034local Something
3035local _class_0
3036local _base_0 = {
3037 umm = "cool"
3038}
3039if _base_0.__index == nil then
3040 _base_0.__index = _base_0
3041end
3042_class_0 = setmetatable({
3043 __init = function() end,
3044 __base = _base_0,
3045 __name = "Something"
3046}, {
3047 __index = _base_0,
3048 __call = function(cls, ...)
3049 local _self_0 = setmetatable({ }, _base_0)
3050 cls.__init(_self_0, ...)
3051 return _self_0
3052 end
3053})
3054_base_0.__class = _class_0
3055Something = _class_0
3056_module_0["Something"] = Something
3057return _module_0
3058local _module_0 = { }
3059local loadstring, tolua
3060do
3061 local _obj_0 = yue
3062 loadstring, tolua = _obj_0.loadstring, _obj_0.to_lua
3063end
3064_module_0["loadstring"], _module_0["tolua"] = loadstring, tolua
3065local fieldA = tb.itemA.fieldA
3066if fieldA == nil then
3067 fieldA = '默认值'
3068end
3069_module_0["fieldA"] = fieldA
3070return _module_0
3071local _module_0 = setmetatable({ }, { })
3072_module_0.itemA = tb
3073getmetatable(_module_0).__index = items
3074_module_0["a-b-c"] = 123
3075return _module_0
3076local _module_0 = { }
3077local d, e, f = 3, 2, 1
3078_module_0[#_module_0 + 1] = d
3079_module_0[#_module_0 + 1] = e
3080_module_0[#_module_0 + 1] = f
3081if this then
3082 _module_0[#_module_0 + 1] = 123
3083else
3084 _module_0[#_module_0 + 1] = 456
3085end
3086local _with_0 = tmp
3087local j = 2000
3088_module_0[#_module_0 + 1] = _with_0
3089return _module_0
3090local _module_0 = nil
3091_module_0 = function()
3092 print("你好")
3093 return 123
3094end
3095return _module_0
3096local hello = "world"
3097local a, b, c = 1, 2, 3
3098hello = 123
3099local x = 1
3100x = x + 1
3101x = x - 1
3102x = x * 10
3103x = x / 10
3104x = x % 10
3105local s = s .. "world"
3106local arg = arg or "默认值"
3107local a = 0
3108local b = 0
3109local c = 0
3110local d = 0
3111local e = 0
3112local x = f()
3113local y = x
3114local z = x
3115do
3116 local a = 1
3117 local x, y, z
3118 print("预先声明后续所有变量为局部变量")
3119 x = function()
3120 return 1 + y + z
3121 end
3122 y, z = 2, 3
3123 instance = Item:new()
3124end
3125do
3126 local X = 1
3127 local B
3128 print("只预先声明后续大写的变量为局部变量")
3129 local a = 1
3130 B = 2
3131end
3132do
3133 a = 1
3134 print("预先声明所有变量为全局变量")
3135 x = function()
3136 return 1 + y + z
3137 end
3138 y, z = 2, 3
3139end
3140do
3141 x = 1
3142 print("只预先声明大写的变量为全局变量")
3143 local a = 1
3144 B = 2
3145 local Temp = "一个局部值"
3146end
3147local thing = {
3148 1,
3149 2
3150}
3151local a, b = thing[1], thing[2]
3152print(a, b)
3153local obj = {
3154 hello = "world",
3155 day = "tuesday",
3156 length = 20
3157}
3158local hello, the_day = obj.hello, obj.day
3159print(hello, the_day)
3160local day = obj.day
3161local obj2 = {
3162 numbers = {
3163 1,
3164 2,
3165 3,
3166 4
3167 },
3168 properties = {
3169 color = "green",
3170 height = 13.5
3171 }
3172}
3173local first, second = obj2.numbers[1], obj2.numbers[2]
3174print(first, second, color)
3175local first, second, color
3176local _obj_0 = obj2
3177first, second, color = _obj_0.numbers[1], _obj_0.numbers[2], _obj_0.properties.color
3178local concat, insert
3179local _obj_0 = table
3180concat, insert = _obj_0.concat, _obj_0.insert
3181local mix, max, rand
3182local _obj_0 = math
3183mix, max, rand = _obj_0.mix, _obj_0.max, _obj_0.random
3184local name, job
3185local _obj_0 = person
3186name, job = _obj_0.name, _obj_0.job
3187if name == nil then
3188 name = "nameless"
3189end
3190if job == nil then
3191 job = "jobless"
3192end
3193local two, four
3194local _obj_0 = items
3195two, four = _obj_0[2], _obj_0[4]
3196local orders = {
3197 "first",
3198 "second",
3199 "third",
3200 "fourth",
3201 "last"
3202}
3203local first, bulk, last = orders[1], (function()
3204 local _accum_0 = { }
3205 local _len_0 = 1
3206 local _max_0 = #orders + -2 + 1
3207 for _index_0 = 2, _max_0 do
3208 local _item_0 = orders[_index_0]
3209 _accum_0[_len_0] = _item_0
3210 _len_0 = _len_0 + 1
3211 end
3212 return _accum_0
3213end)(), orders[#orders]
3214print(first)
3215print(bulk)
3216print(last)
3217local first, rest
3218do
3219 local _obj_0 = orders
3220 first, rest = _obj_0[1], (function()
3221 local _accum_0 = { }
3222 local _len_0 = 1
3223 local _max_0 = #_obj_0
3224 for _index_0 = 2, _max_0 do
3225 local _item_0 = _obj_0[_index_0]
3226 _accum_0[_len_0] = _item_0
3227 _len_0 = _len_0 + 1
3228 end
3229 return _accum_0
3230 end)()
3231end
3232local start, last
3233do
3234 local _obj_0 = orders
3235 start, last = (function()
3236 local _accum_0 = { }
3237 local _len_0 = 1
3238 local _max_0 = #_obj_0 + -2 + 1
3239 for _index_0 = 1, _max_0 do
3240 local _item_0 = _obj_0[_index_0]
3241 _accum_0[_len_0] = _item_0
3242 _len_0 = _len_0 + 1
3243 end
3244 return _accum_0
3245 end)(), _obj_0[#_obj_0]
3246end
3247local _obj_0 = orders
3248first, last = _obj_0[1], _obj_0[#_obj_0]
3249local tuples = {
3250 {
3251 "hello",
3252 "world"
3253 },
3254 {
3255 "egg",
3256 "head"
3257 }
3258}
3259for _index_0 = 1, #tuples do
3260 local _des_0 = tuples[_index_0]
3261 local left, right = _des_0[1], _des_0[2]
3262 print(left, right)
3263end
3264local user = database.find_user("moon")
3265if user then
3266 print(user.name)
3267end
3268local hello = os.getenv("hello")
3269if hello then
3270 print("你有 hello", hello)
3271else
3272 local world = os.getenv("world")
3273 if world then
3274 print("你有 world", world)
3275 else
3276 print("什么都没有 :(")
3277 end
3278end
3279do
3280 local success, result = pcall(function()
3281 return "无报错地获取结果"
3282 end)
3283 if success then
3284 print(result)
3285 end
3286end
3287print("好的")
3288repeat
3289 local byte = stream:read_one()
3290 if byte then
3291 print(byte)
3292 else
3293 break
3294 end
3295until false
3296local list = {
3297 1,
3298 2,
3299 3,
3300 4,
3301 5
3302}
3303local fn
3304fn = function(ok)
3305 return ok, table.unpack(list)
3306end
3307(function(_arg_0, ...)
3308 local ok = _arg_0
3309 local count = select('#', ...)
3310 local first = select(1, ...)
3311 return print(ok, count, first)
3312end)(fn(true))
3313local a = 1
3314local b = 2
3315print(a + b)
3316Rx.Observable.fromRange(1, 8):filter(function(x)
3317 return x % 2 == 0
3318end):concat(Rx.Observable.of('who do we appreciate')):map(function(value)
3319 return value .. '!'
3320end):subscribe(print)
3321local str = strA .. strB .. strC
3322func(3000, "192.168.1.1")
3323xpcall(function()
3324 return func(1, 2, 3)
3325end, function(err)
3326 return print(yue.traceback(err))
3327end)
3328local success, result = xpcall(function()
3329 return func(1, 2, 3)
3330end, function(err)
3331 return yue.traceback(err)
3332end)
3333xpcall(function()
3334 return func(1, 2, 3)
3335end, function(err)
3336 return print(yue.traceback(err))
3337end)
3338success, result = pcall(function()
3339 return func(1, 2, 3)
3340end)
3341pcall(function()
3342 print("尝试中")
3343 return func(1, 2, 3)
3344end)
3345success, result = xpcall(function()
3346 return func(1, 2, 3)
3347end, function(err)
3348 return print(yue.traceback(err))
3349end)
3350if success then
3351 print(result)
3352end
3353local a, b, c
3354do
3355 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
3356 return func()
3357 end)
3358 if _ok_0 then
3359 a, b, c = _ret_0, _ret_1, _ret_2
3360 end
3361end
3362do
3363 local _exp_0 = ((function()
3364 return (function(_arg_0, ...)
3365 local _ok_0 = _arg_0
3366 if _ok_0 then
3367 return ...
3368 end
3369 end)(pcall(function()
3370 return func()
3371 end))
3372 end)())
3373 if _exp_0 ~= nil then
3374 a = _exp_0
3375 else
3376 a = "default"
3377 end
3378end
3379f((function()
3380 return (function(_arg_0, ...)
3381 local _ok_0 = _arg_0
3382 if _ok_0 then
3383 return ...
3384 end
3385 end)(pcall(function()
3386 return func()
3387 end))
3388end)())
3389f((function()
3390 return (function(_arg_0, ...)
3391 local _ok_0 = _arg_0
3392 if _ok_0 then
3393 return ...
3394 end
3395 end)(xpcall(function()
3396 print(123)
3397 return func()
3398 end, function(e)
3399 print(e)
3400 return e
3401 end))
3402end)())
3403local a <const> = 123
3404local _ <close> = setmetatable({ }, {
3405 __close = function()
3406 return print("超出范围。")
3407 end
3408})
3409local a, b, c, d
3410local _obj_0 = tb
3411a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2]
3412Constant = 123
3413local some_string = "这是一个字符串\n 并包括一个换行。"
3414print("我有" .. tostring(math.random() * 100) .. "%的把握。")
3415local integer = 1000000
3416local hex = 0xEFBBBF
3417local binary = 19
3418local str = "key: value\nlist:\n - item1\n - " .. tostring(expr)
3419local fn
3420fn = function()
3421 local str = "foo:\n bar: baz"
3422 return str
3423end
3424local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'"
3425local my_function
3426my_function = function() end
3427my_function()
3428local func_a
3429func_a = function()
3430 return print("你好,世界")
3431end
3432local func_b
3433func_b = function()
3434 local value = 100
3435 return print("这个值是:", value)
3436end
3437func_a()
3438func_b()
3439local sum
3440sum = function(x, y)
3441 return print("数字的和", x + y)
3442end
3443sum(10, 20)
3444print(sum(10, 20))
3445a(b(c("a", "b", "c")))
3446print("x:", sum(10, 20), "y:", sum(30, 40))
3447local sum
3448sum = function(x, y)
3449 return x + y
3450end
3451print("数字的和是", sum(10, 20))
3452local sum
3453sum = function(x, y)
3454 return x + y
3455end
3456local mystery
3457mystery = function(x, y)
3458 return x + y, x - y
3459end
3460local a, b = mystery(10, 20)
3461local func
3462func = function(self, num)
3463 return self.value + num
3464end
3465local my_function
3466my_function = function(name, height)
3467 if name == nil then
3468 name = "某物"
3469 end
3470 if height == nil then
3471 height = 100
3472 end
3473 print("你好,我是", name)
3474 return print("我的高度是", height)
3475end
3476local some_args
3477some_args = function(x, y)
3478 if x == nil then
3479 x = 100
3480 end
3481 if y == nil then
3482 y = x + 1000
3483 end
3484 return print(x + y)
3485end
3486my_func(5, 4, 3, 8, 9, 10)
3487cool_func(1, 2, 3, 4, 5, 6, 7, 8)
3488my_func(5, 6, 7, 6, another_func(6, 7, 8, 9, 1, 2), 5, 4)
3489local x = {
3490 1,
3491 2,
3492 3,
3493 4,
3494 a_func(4, 5, 5, 6),
3495 8,
3496 9,
3497 10
3498}
3499local y = {
3500 my_func(1, 2, 3, 4, 5),
3501 5,
3502 6,
3503 7
3504}
3505if func(1, 2, 3, "你好", "世界") then
3506 print("你好")
3507 print("我在if内部")
3508end
3509if func(1, 2, 3, "你好", "世界") then
3510 print("你好")
3511 print("我在if内部")
3512end
3513local f1
3514f1 = function(_arg_0)
3515 local a, b, c
3516 a, b, c = _arg_0.a, _arg_0.b, _arg_0.c
3517 return print(a, b, c)
3518end
3519f1({
3520 a = 1,
3521 b = "2",
3522 c = { }
3523})
3524local f2
3525f2 = function(_arg_0, c)
3526 local a1, b
3527 a1, b = _arg_0.a, _arg_0.b
3528 if a1 == nil then
3529 a1 = 123
3530 end
3531 if b == nil then
3532 b = 'abc'
3533 end
3534 if c == nil then
3535 c = { }
3536 end
3537 return print(a1, b, c)
3538end
3539local arg1 = {
3540 a = 0
3541}
3542f2(arg1, arg2)
3543local findFirstEven
3544findFirstEven = function(list)
3545 for _index_0 = 1, #list do
3546 local item = list[_index_0]
3547 if type(item) == "table" then
3548 for _index_1 = 1, #item do
3549 local sub = item[_index_1]
3550 if sub % 2 == 0 then
3551 return sub
3552 end
3553 end
3554 end
3555 end
3556 return nil
3557end
3558local findFirstEven
3559findFirstEven = function(list)
3560 for _index_0 = 1, #list do
3561 local item = list[_index_0]
3562 if type(item) == "table" then
3563 for _index_1 = 1, #item do
3564 local sub = item[_index_1]
3565 if sub % 2 == 0 then
3566 return sub
3567 end
3568 end
3569 end
3570 end
3571 return nil
3572end
3573local f
3574f = function(...)
3575 local t = {
3576 n = select("#", ...),
3577 ...
3578 }
3579 print("参数个数:", t.n)
3580 print("表长度:", #t)
3581 for i = 1, t.n do
3582 print(t[i])
3583 end
3584end
3585f(1, 2, 3)
3586f("a", "b", "c", "d")
3587f()
3588local process
3589process = function(...)
3590 local args = {
3591 n = select("#", ...),
3592 ...
3593 }
3594 local sum = 0
3595 for i = 1, args.n do
3596 if args[i] ~= nil and type(args[i]) == "number" then
3597 sum = sum + args[i]
3598 end
3599 end
3600 return sum
3601end
3602process(1, nil, 3, nil, 5)
3603f(function()
3604 return print("hello")
3605end)
3606f(function(self)
3607 return print(self.value)
3608end)
3609map(function(x)
3610 return x * 2
3611end, {
3612 1,
3613 2,
3614 3
3615})
3616local result, msg
3617do
3618 result, msg = readAsync("文件名.txt", function(data)
3619 print(data)
3620 return processAsync(data, function(info)
3621 return check(info)
3622 end)
3623 end)
3624end
3625print(result, msg)
3626local some_values = {
3627 1,
3628 2,
3629 3,
3630 4
3631}
3632local some_values = {
3633 name = "Bill",
3634 age = 200,
3635 ["favorite food"] = "rice"
3636}
3637local profile = {
3638 height = "4英尺",
3639 shoe_size = 13,
3640 favorite_foods = {
3641 "冰淇淋",
3642 "甜甜圈"
3643 }
3644}
3645local values = {
3646 1,
3647 2,
3648 3,
3649 4,
3650 5,
3651 6,
3652 7,
3653 8,
3654 name = "超人",
3655 occupation = "打击犯罪"
3656}
3657my_function({
3658 dance = "探戈",
3659 partner = "无"
3660})
3661local y = {
3662 type = "狗",
3663 legs = 4,
3664 tails = 1
3665}
3666local tbl = {
3667 ["do"] = "某事",
3668 ["end"] = "饥饿"
3669}
3670local hair = "金色"
3671local height = 200
3672local person = {
3673 hair = hair,
3674 height = height,
3675 shoe_size = 40
3676}
3677print_table({
3678 hair = hair,
3679 height = height
3680})
3681local t = {
3682 [1 + 2] = "你好",
3683 ["你好 世界"] = true
3684}
3685local some_values = {
3686 1,
3687 2,
3688 3,
3689 4
3690}
3691local list_with_one_element = {
3692 1
3693}
3694local items = {
3695 1,
3696 2,
3697 3,
3698 4
3699}
3700local doubled
3701local _accum_0 = { }
3702local _len_0 = 1
3703for i, item in ipairs(items) do
3704 _accum_0[_len_0] = item * 2
3705 _len_0 = _len_0 + 1
3706end
3707doubled = _accum_0
3708local slice
3709local _accum_0 = { }
3710local _len_0 = 1
3711for i, item in ipairs(items) do
3712 if i > 1 and i < 3 then
3713 _accum_0[_len_0] = item
3714 _len_0 = _len_0 + 1
3715 end
3716end
3717slice = _accum_0
3718local doubled
3719local _accum_0 = { }
3720local _len_0 = 1
3721local _list_0 = items
3722for _index_0 = 1, #_list_0 do
3723 local item = _list_0[_index_0]
3724 _accum_0[_len_0] = item * 2
3725 _len_0 = _len_0 + 1
3726end
3727doubled = _accum_0
3728local data = {
3729 a = {
3730 1,
3731 2,
3732 3
3733 },
3734 b = {
3735 4,
3736 5,
3737 6
3738 }
3739}
3740local flat
3741local _accum_0 = { }
3742for k, v in pairs(data) do
3743 local _len_0 = #_accum_0 + 1
3744 for _index_0 = 1, #v do
3745 local _elm_0 = v[_index_0]
3746 _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1
3747 end
3748end
3749flat = _accum_0
3750local x_coords = {
3751 4,
3752 5,
3753 6,
3754 7
3755}
3756local y_coords = {
3757 9,
3758 2,
3759 3
3760}
3761local points
3762local _accum_0 = { }
3763local _len_0 = 1
3764for _index_0 = 1, #x_coords do
3765 local x = x_coords[_index_0]
3766 for _index_1 = 1, #y_coords do
3767 local y = y_coords[_index_1]
3768 _accum_0[_len_0] = {
3769 x,
3770 y
3771 }
3772 _len_0 = _len_0 + 1
3773 end
3774end
3775points = _accum_0
3776local evens
3777local _accum_0 = { }
3778local _len_0 = 1
3779for i = 1, 100 do
3780 if i % 2 == 0 then
3781 _accum_0[_len_0] = i
3782 _len_0 = _len_0 + 1
3783 end
3784end
3785evens = _accum_0
3786local thing = {
3787 color = "red",
3788 name = "fast",
3789 width = 123
3790}
3791local thing_copy
3792local _tbl_0 = { }
3793for k, v in pairs(thing) do
3794 _tbl_0[k] = v
3795end
3796thing_copy = _tbl_0
3797local no_color
3798local _tbl_0 = { }
3799for k, v in pairs(thing) do
3800 if k ~= "color" then
3801 _tbl_0[k] = v
3802 end
3803end
3804no_color = _tbl_0
3805local numbers = {
3806 1,
3807 2,
3808 3,
3809 4
3810}
3811local sqrts
3812local _tbl_0 = { }
3813for _index_0 = 1, #numbers do
3814 local i = numbers[_index_0]
3815 _tbl_0[i] = math.sqrt(i)
3816end
3817sqrts = _tbl_0
3818local tuples = {
3819 {
3820 "hello",
3821 "world"
3822 },
3823 {
3824 "foo",
3825 "bar"
3826 }
3827}
3828local tbl
3829local _tbl_0 = { }
3830for _index_0 = 1, #tuples do
3831 local tuple = tuples[_index_0]
3832 local _key_0, _val_0 = unpack(tuple)
3833 _tbl_0[_key_0] = _val_0
3834end
3835tbl = _tbl_0
3836local slice
3837local _accum_0 = { }
3838local _len_0 = 1
3839local _list_0 = items
3840for _index_0 = 1, 5 do
3841 local item = _list_0[_index_0]
3842 _accum_0[_len_0] = item
3843 _len_0 = _len_0 + 1
3844end
3845slice = _accum_0
3846local slice
3847local _accum_0 = { }
3848local _len_0 = 1
3849local _list_0 = items
3850local _max_0 = #_list_0
3851for _index_0 = 2, _max_0 do
3852 local item = _list_0[_index_0]
3853 _accum_0[_len_0] = item
3854 _len_0 = _len_0 + 1
3855end
3856slice = _accum_0
3857local slice
3858local _accum_0 = { }
3859local _len_0 = 1
3860local _list_0 = items
3861local _max_0 = #_list_0
3862for _index_0 = 1, _max_0, 2 do
3863 local item = _list_0[_index_0]
3864 _accum_0[_len_0] = item
3865 _len_0 = _len_0 + 1
3866end
3867slice = _accum_0
3868local slice
3869local _accum_0 = { }
3870local _len_0 = 1
3871local _list_0 = items
3872local _min_0 = #_list_0 + -4 + 1
3873local _max_0 = #_list_0 + -1 + 1
3874for _index_0 = _min_0, _max_0 do
3875 local item = _list_0[_index_0]
3876 _accum_0[_len_0] = item
3877 _len_0 = _len_0 + 1
3878end
3879slice = _accum_0
3880local reverse_slice
3881local _accum_0 = { }
3882local _len_0 = 1
3883local _list_0 = items
3884local _min_0 = #_list_0 + -1 + 1
3885for _index_0 = _min_0, 1, -1 do
3886 local item = _list_0[_index_0]
3887 _accum_0[_len_0] = item
3888 _len_0 = _len_0 + 1
3889end
3890reverse_slice = _accum_0
3891local sub_list
3892local _accum_0 = { }
3893local _len_0 = 1
3894local _list_0 = items
3895for _index_0 = 2, 4 do
3896 local _item_0 = _list_0[_index_0]
3897 _accum_0[_len_0] = _item_0
3898 _len_0 = _len_0 + 1
3899end
3900sub_list = _accum_0
3901for i = 10, 20 do
3902 print(i)
3903end
3904for k = 1, 15, 2 do
3905 print(k)
3906end
3907for key, value in pairs(object) do
3908 print(key, value)
3909end
3910local _list_0 = items
3911for _index_0 = 2, 4 do
3912 local item = _list_0[_index_0]
3913 print(item)
3914end
3915local _list_0 = items
3916for _index_0 = 1, #_list_0 do
3917 local item = _list_0[_index_0]
3918 print(item)
3919end
3920for j = 1, 10, 3 do
3921 print(j)
3922end
3923local doubled_evens
3924local _accum_0 = { }
3925local _len_0 = 1
3926for i = 1, 20 do
3927 if i % 2 == 0 then
3928 _accum_0[_len_0] = i * 2
3929 _len_0 = _len_0 + 1
3930 else
3931 _accum_0[_len_0] = i
3932 _len_0 = _len_0 + 1
3933 end
3934end
3935doubled_evens = _accum_0
3936local first_large
3937local _accum_0
3938local _list_0 = numbers
3939for _index_0 = 1, #_list_0 do
3940 local n = _list_0[_index_0]
3941 if n > 10 then
3942 _accum_0 = n
3943 break
3944 end
3945end
3946first_large = _accum_0
3947local func_a
3948func_a = function()
3949 for i = 1, 10 do
3950 print(i)
3951 end
3952end
3953local func_b
3954func_b = function()
3955 local _accum_0 = { }
3956 local _len_0 = 1
3957 for i = 1, 10 do
3958 _accum_0[_len_0] = i
3959 _len_0 = _len_0 + 1
3960 end
3961 return _accum_0
3962end
3963print(func_a())
3964print(func_b())
3965local i = 10
3966repeat
3967 print(i)
3968 i = i - 1
3969until i == 0
3970local i = 10
3971while i > 0 do
3972 print(i)
3973 i = i - 1
3974end
3975while running == true do
3976 my_function()
3977end
3978local i = 10
3979while not (i == 0) do
3980 print(i)
3981 i = i - 1
3982end
3983while not (running == false) do
3984 my_function()
3985end
3986local i = 0
3987while i < 10 do
3988 i = i + 1
3989 if i % 2 == 0 then
3990 goto _continue_0
3991 end
3992 print(i)
3993 ::_continue_0::
3994end
3995local my_numbers = {
3996 1,
3997 2,
3998 3,
3999 4,
4000 5,
4001 6
4002}
4003local odds
4004local _accum_0 = { }
4005local _len_0 = 1
4006for _index_0 = 1, #my_numbers do
4007 local x = my_numbers[_index_0]
4008 if x % 2 == 1 then
4009 goto _continue_0
4010 end
4011 _accum_0[_len_0] = x
4012 _len_0 = _len_0 + 1
4013 ::_continue_0::
4014end
4015odds = _accum_0
4016local have_coins = false
4017if have_coins then
4018 print("有硬币")
4019else
4020 print("没有硬币")
4021end
4022local have_coins = false
4023if have_coins then
4024 print("有硬币")
4025else
4026 print("没有硬币")
4027end
4028local have_coins = false
4029print((function()
4030 if have_coins then
4031 return "有硬币"
4032 else
4033 return "没有硬币"
4034 end
4035end)())
4036local is_tall
4037is_tall = function(name)
4038 if name == "Rob" then
4039 return true
4040 else
4041 return false
4042 end
4043end
4044local message
4045if is_tall("Rob") then
4046 message = "我很高"
4047else
4048 message = "我不是很高"
4049end
4050print(message)
4051if not (os.date("%A") == "Monday") then
4052 print("今天不是星期一!")
4053end
4054if not (math.random() > 0.1) then
4055 print("你真幸运!")
4056end
4057local a = 5
4058if (1 == a or 3 == a or 5 == a or 7 == a) then
4059 print("检查离散值的相等性")
4060end
4061if (function()
4062 local _check_0 = list
4063 for _index_0 = 1, #_check_0 do
4064 if _check_0[_index_0] == a then
4065 return true
4066 end
4067 end
4068 return false
4069end)() then
4070 print("检查`a`是否在列表中")
4071end
4072if not (math.random() > 0.1) then
4073 print("你很幸运!")
4074end
4075if name == "Rob" then
4076 print("你好,世界")
4077end
4078local _list_0 = items
4079for _index_0 = 1, #_list_0 do
4080 local item = _list_0[_index_0]
4081 print("项目: ", item)
4082end
4083while game:isRunning() do
4084 game:update()
4085end
4086while not reader:eof() do
4087 reader:parse_line()
4088end
4089local name = "Dan"
4090if "Robert" == name then
4091 print("你是Robert")
4092elseif "Dan" == name or "Daniel" == name then
4093 print("你的名字是Dan")
4094else
4095 print("我不认识你,你的名字是" .. tostring(name))
4096end
4097local b = 1
4098local next_number
4099if 1 == b then
4100 next_number = 2
4101elseif 2 == b then
4102 next_number = 3
4103else
4104 next_number = error("数字数得太大了!")
4105end
4106local msg
4107local _exp_0 = math.random(1, 5)
4108if 1 == _exp_0 then
4109 msg = "你很幸运"
4110elseif 2 == _exp_0 then
4111 msg = "你差点很幸运"
4112else
4113 msg = "不太幸运"
4114end
4115do
4116 local _exp_0 = math.random(1, 5)
4117 if 1 == _exp_0 then
4118 print("你很幸运")
4119 else
4120 print("不太幸运")
4121 end
4122end
4123local _exp_0 = math.random(1, 5)
4124if 1 == _exp_0 then
4125 print("你很幸运")
4126else
4127 print("不太幸运")
4128end
4129local items = {
4130 {
4131 x = 100,
4132 y = 200
4133 },
4134 {
4135 width = 300,
4136 height = 400
4137 }
4138}
4139for _index_0 = 1, #items do
4140 local item = items[_index_0]
4141 local _type_0 = type(item)
4142 local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4143 local _match_0 = false
4144 if _tab_0 then
4145 local x = item.x
4146 local y = item.y
4147 if x ~= nil and y ~= nil then
4148 _match_0 = true
4149 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
4150 end
4151 end
4152 if not _match_0 then
4153 if _tab_0 then
4154 local width = item.width
4155 local height = item.height
4156 if width ~= nil and height ~= nil then
4157 print("尺寸 " .. tostring(width) .. ", " .. tostring(height))
4158 end
4159 end
4160 end
4161end
4162local item = { }
4163local x, y = item.pos.x, item.pos.y
4164if x == nil then
4165 x = 50
4166end
4167if y == nil then
4168 y = 200
4169end
4170local _type_0 = type(item)
4171local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4172if _tab_0 then
4173 do
4174 local _obj_0 = item.pos
4175 local _type_1 = type(_obj_0)
4176 if "table" == _type_1 or "userdata" == _type_1 then
4177 x = _obj_0.x
4178 end
4179 end
4180 do
4181 local _obj_0 = item.pos
4182 local _type_1 = type(_obj_0)
4183 if "table" == _type_1 or "userdata" == _type_1 then
4184 y = _obj_0.y
4185 end
4186 end
4187 if x == nil then
4188 x = 50
4189 end
4190 if y == nil then
4191 y = 200
4192 end
4193 print("Vec2 " .. tostring(x) .. ", " .. tostring(y))
4194end
4195local _exp_0 = tb
4196local _type_0 = type(_exp_0)
4197local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4198local _match_0 = false
4199if _tab_0 then
4200 if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then
4201 _match_0 = true
4202 print("1, 2, 3")
4203 end
4204end
4205if not _match_0 then
4206 local _match_1 = false
4207 if _tab_0 then
4208 local b = _exp_0[2]
4209 if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then
4210 _match_1 = true
4211 print("1, " .. tostring(b) .. ", 3")
4212 end
4213 end
4214 if not _match_1 then
4215 if _tab_0 then
4216 local b = _exp_0[3]
4217 if b == nil then
4218 b = 3
4219 end
4220 if 1 == _exp_0[1] and 2 == _exp_0[2] then
4221 print("1, 2, " .. tostring(b))
4222 end
4223 end
4224 end
4225end
4226local _exp_0 = tb
4227local _type_0 = type(_exp_0)
4228local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4229local _match_0 = false
4230if _tab_0 then
4231 local result = _exp_0.result
4232 if true == _exp_0.success and result ~= nil then
4233 _match_0 = true
4234 print("成功", result)
4235 end
4236end
4237if not _match_0 then
4238 local _match_1 = false
4239 if _tab_0 then
4240 if false == _exp_0.success then
4241 _match_1 = true
4242 print("失败", result)
4243 end
4244 end
4245 if not _match_1 then
4246 print("无效值")
4247 end
4248end
4249local _exp_0 = tb
4250local _type_0 = type(_exp_0)
4251local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4252local _match_0 = false
4253if _tab_0 then
4254 local content
4255 do
4256 local _obj_0 = _exp_0.data
4257 local _type_1 = type(_obj_0)
4258 if "table" == _type_1 or "userdata" == _type_1 then
4259 content = _obj_0.content
4260 end
4261 end
4262 local _val_0
4263 do
4264 local _obj_0 = _exp_0.data
4265 if _obj_0 ~= nil then
4266 _val_0 = _obj_0.type
4267 end
4268 end
4269 if "success" == _val_0 and content ~= nil then
4270 _match_0 = true
4271 print("成功", content)
4272 end
4273end
4274if not _match_0 then
4275 local _match_1 = false
4276 if _tab_0 then
4277 local content
4278 do
4279 local _obj_0 = _exp_0.data
4280 local _type_1 = type(_obj_0)
4281 if "table" == _type_1 or "userdata" == _type_1 then
4282 content = _obj_0.content
4283 end
4284 end
4285 local _val_0
4286 do
4287 local _obj_0 = _exp_0.data
4288 if _obj_0 ~= nil then
4289 _val_0 = _obj_0.type
4290 end
4291 end
4292 if "error" == _val_0 and content ~= nil then
4293 _match_1 = true
4294 print("失败", content)
4295 end
4296 end
4297 if not _match_1 then
4298 print("无效值")
4299 end
4300end
4301local _exp_0 = tb
4302local _type_0 = type(_exp_0)
4303local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4304if _tab_0 then
4305 local fourth = _exp_0[4]
4306 local _val_0
4307 do
4308 local _obj_0 = _exp_0[1]
4309 if _obj_0 ~= nil then
4310 _val_0 = _obj_0.a
4311 end
4312 end
4313 local _val_1
4314 do
4315 local _obj_0 = _exp_0[1]
4316 if _obj_0 ~= nil then
4317 _val_1 = _obj_0.b
4318 end
4319 end
4320 local _val_2
4321 do
4322 local _obj_0 = _exp_0[2]
4323 if _obj_0 ~= nil then
4324 _val_2 = _obj_0.a
4325 end
4326 end
4327 local _val_3
4328 do
4329 local _obj_0 = _exp_0[2]
4330 if _obj_0 ~= nil then
4331 _val_3 = _obj_0.b
4332 end
4333 end
4334 local _val_4
4335 do
4336 local _obj_0 = _exp_0[3]
4337 if _obj_0 ~= nil then
4338 _val_4 = _obj_0.a
4339 end
4340 end
4341 local _val_5
4342 do
4343 local _obj_0 = _exp_0[3]
4344 if _obj_0 ~= nil then
4345 _val_5 = _obj_0.b
4346 end
4347 end
4348 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
4349 print("匹配成功", fourth)
4350 end
4351end
4352local segments = {
4353 "admin",
4354 "users",
4355 "logs",
4356 "view"
4357}
4358local _type_0 = type(segments)
4359local _tab_0 = "table" == _type_0 or "userdata" == _type_0
4360if _tab_0 then
4361 local groups
4362 do
4363 local _accum_0 = { }
4364 local _len_0 = 1
4365 local _max_0 = #segments + -3 + 1
4366 for _index_0 = 1, _max_0 do
4367 local _item_0 = segments[_index_0]
4368 _accum_0[_len_0] = _item_0
4369 _len_0 = _len_0 + 1
4370 end
4371 groups = _accum_0
4372 end
4373 local resource = segments[#segments - 1]
4374 local action = segments[#segments]
4375 if resource ~= nil and action ~= nil then
4376 print("Group:", groups)
4377 print("Resource:", resource)
4378 print("Action:", action)
4379 end
4380end
4381local Inventory 4313local Inventory
4382local _class_0 4314local _class_0
4383local _base_0 = { 4315local _base_0 = {
@@ -5038,6 +4970,46 @@ local _with_0 = obj
5038if _with_0 ~= nil then 4970if _with_0 ~= nil then
5039 print(obj.name) 4971 print(obj.name)
5040end 4972end
4973local _with_0 = Person()
4974_with_0.name = "Oswald"
4975_with_0:add_relative(my_dad)
4976_with_0:save()
4977print(_with_0.name)
4978local file
4979local _with_0 = File("favorite_foods.txt")
4980_with_0:set_encoding("utf8")
4981file = _with_0
4982local create_person
4983create_person = function(name, relatives)
4984 local _with_0 = Person()
4985 _with_0.name = name
4986 for _index_0 = 1, #relatives do
4987 local relative = relatives[_index_0]
4988 _with_0:add_relative(relative)
4989 end
4990 return _with_0
4991end
4992local me = create_person("Leaf", {
4993 dad,
4994 mother,
4995 sister
4996})
4997local str = "你好"
4998print("原始:", str)
4999print("大写:", str:upper())
5000local _with_0 = tb
5001_with_0[1] = 1
5002print(_with_0[2])
5003do
5004 local _with_1 = _with_0[abc]
5005 _with_1[3] = _with_1[2]:func()
5006 _with_1["key-name"] = value
5007end
5008_with_0[#_with_0 + 1] = "abc"
5009local _with_0 = obj
5010if _with_0 ~= nil then
5011 print(obj.name)
5012end
5041do 5013do
5042 local var = "hello" 5014 local var = "hello"
5043 print(var) 5015 print(var)
@@ -5059,6 +5031,46 @@ local tbl = {
5059 return 1234 5031 return 1234
5060 end)() 5032 end)()
5061} 5033}
5034do
5035 local var = "hello"
5036 print(var)
5037end
5038print(var)
5039local counter
5040do
5041 local i = 0
5042 counter = function()
5043 i = i + 1
5044 return i
5045 end
5046end
5047print(counter())
5048print(counter())
5049local tbl = {
5050 key = (function()
5051 print("分配键值!")
5052 return 1234
5053 end)()
5054}
5055local my_object = {
5056 value = 1000,
5057 write = function(self)
5058 return print("值为:", self.value)
5059 end
5060}
5061local run_callback
5062run_callback = function(func)
5063 print("运行回调...")
5064 return func()
5065end
5066run_callback(my_object.write)
5067run_callback((function()
5068 local _base_0 = my_object
5069 local _fn_0 = _base_0.write
5070 return _fn_0 and function(...)
5071 return _fn_0(_base_0, ...)
5072 end
5073end)())
5062local my_object = { 5074local my_object = {
5063 value = 1000, 5075 value = 1000,
5064 write = function(self) 5076 write = function(self)
@@ -5106,3 +5118,31 @@ my_func = function(add)
5106end 5118end
5107my_func(22) 5119my_func(22)
5108print(i, k) 5120print(i, k)
5121local i = 100
5122local my_func
5123my_func = function()
5124 i = 10
5125 while i > 0 do
5126 print(i)
5127 i = i - 1
5128 end
5129end
5130my_func()
5131print(i)
5132local i = 100
5133local my_func
5134my_func = function()
5135 local i = "hello"
5136end
5137my_func()
5138print(i)
5139local tmp = 1213
5140local i, k = 100, 50
5141local my_func
5142my_func = function(add)
5143 local tmp = tmp + add
5144 i = i + tmp
5145 k = k + tmp
5146end
5147my_func(22)
5148print(i, k)
diff --git a/spec/outputs/compile_doc.lua b/spec/outputs/compile_doc.lua
index e7d307d..cb359a1 100644
--- a/spec/outputs/compile_doc.lua
+++ b/spec/outputs/compile_doc.lua
@@ -2,52 +2,113 @@ local outputFolder = ...
2local _list_0 = { 2local _list_0 = {
3 { 3 {
4 "codes_from_doc.lua", 4 "codes_from_doc.lua",
5 "doc/docs/doc/index.md" 5 {
6 "doc/docs/doc/introduction.md",
7 "doc/docs/doc/macro.md",
8 "doc/docs/doc/operator.md",
9 "doc/docs/doc/module.md",
10 "doc/docs/doc/assignment.md",
11 "doc/docs/doc/destructuring-assignment.md",
12 "doc/docs/doc/if-assignment.md",
13 "doc/docs/doc/varargs-assignment.md",
14 "doc/docs/doc/whitespace.md",
15 "doc/docs/doc/comment.md",
16 "doc/docs/doc/try.md",
17 "doc/docs/doc/attributes.md",
18 "doc/docs/doc/literals.md",
19 "doc/docs/doc/function-literals.md",
20 "doc/docs/doc/backcalls.md",
21 "doc/docs/doc/table-literals.md",
22 "doc/docs/doc/comprehensions.md",
23 "doc/docs/doc/for-loop.md",
24 "doc/docs/doc/while-loop.md",
25 "doc/docs/doc/continue.md",
26 "doc/docs/doc/conditionals.md",
27 "doc/docs/doc/line-decorators.md",
28 "doc/docs/doc/switch.md",
29 "doc/docs/doc/object-oriented-programming.md",
30 "doc/docs/doc/with-statement.md",
31 "doc/docs/doc/do.md",
32 "doc/docs/doc/function-stubs.md",
33 "doc/docs/doc/the-using-clause-controlling-destructive-assignment.md"
34 }
6 }, 35 },
7 { 36 {
8 "codes_from_doc_zh.lua", 37 "codes_from_doc_zh.lua",
9 "doc/docs/zh/doc/index.md" 38 {
39 "doc/docs/zh/doc/introduction.md",
40 "doc/docs/zh/doc/macro.md",
41 "doc/docs/zh/doc/operator.md",
42 "doc/docs/zh/doc/module.md",
43 "doc/docs/zh/doc/assignment.md",
44 "doc/docs/zh/doc/destructuring-assignment.md",
45 "doc/docs/zh/doc/if-assignment.md",
46 "doc/docs/zh/doc/varargs-assignment.md",
47 "doc/docs/zh/doc/whitespace.md",
48 "doc/docs/zh/doc/comment.md",
49 "doc/docs/zh/doc/try.md",
50 "doc/docs/zh/doc/attributes.md",
51 "doc/docs/zh/doc/literals.md",
52 "doc/docs/zh/doc/function-literals.md",
53 "doc/docs/zh/doc/backcalls.md",
54 "doc/docs/zh/doc/table-literals.md",
55 "doc/docs/zh/doc/comprehensions.md",
56 "doc/docs/zh/doc/for-loop.md",
57 "doc/docs/zh/doc/while-loop.md",
58 "doc/docs/zh/doc/continue.md",
59 "doc/docs/zh/doc/conditionals.md",
60 "doc/docs/zh/doc/line-decorators.md",
61 "doc/docs/zh/doc/switch.md",
62 "doc/docs/zh/doc/object-oriented-programming.md",
63 "doc/docs/zh/doc/with-statement.md",
64 "doc/docs/zh/doc/do.md",
65 "doc/docs/zh/doc/function-stubs.md",
66 "doc/docs/zh/doc/the-using-clause-controlling-destructive-assignment.md"
67 }
10 } 68 }
11} 69}
12for _index_0 = 1, #_list_0 do 70for _index_0 = 1, #_list_0 do
13 local _des_0 = _list_0[_index_0] 71 local _des_0 = _list_0[_index_0]
14 local compiledFile, docFile = _des_0[1], _des_0[2] 72 local compiledFile, docFiles = _des_0[1], _des_0[2]
15 local input 73 local codes = { }
16 local _with_0 = io.open(docFile) 74 for _index_1 = 1, #docFiles do
17 if _with_0 ~= nil then 75 local docFile = docFiles[_index_1]
18 local to_lua = require("yue").to_lua 76 local input
19 local text = _with_0:read("*a") 77 local _with_0 = io.open(docFile)
20 local codes = { } 78 if _with_0 ~= nil then
21 for code in text:gmatch("```yuescript[\r\n]+(.-)```[^%w]") do 79 local to_lua = require("yue").to_lua
22 local result, err = to_lua(code, { 80 local text = _with_0:read("*a")
23 implicit_return_root = false, 81 for code in text:gmatch("```yuescript[\r\n]+(.-)```[^%w]") do
24 reserve_line_number = false 82 local result, err = to_lua(code, {
25 }) 83 implicit_return_root = false,
26 if result then 84 reserve_line_number = false
27 codes[#codes + 1] = result 85 })
28 elseif not err:match("macro exporting module only accepts macro definition") then 86 if result then
29 print(err) 87 codes[#codes + 1] = result
30 os.exit(1) 88 elseif not err:match("macro exporting module only accepts macro definition") then
89 print(err)
90 os.exit(1)
91 end
31 end 92 end
32 end 93 for code in text:gmatch("```yue[\r\n]+(.-)```[^%w]") do
33 for code in text:gmatch("```yue[\r\n]+(.-)```[^%w]") do 94 local result, err = to_lua(code, {
34 local result, err = to_lua(code, { 95 implicit_return_root = false,
35 implicit_return_root = false, 96 reserve_line_number = false
36 reserve_line_number = false 97 })
37 }) 98 if result then
38 if result then 99 codes[#codes + 1] = result
39 codes[#codes + 1] = result 100 else
40 else 101 print(err)
41 print(err) 102 os.exit(1)
42 os.exit(1) 103 end
43 end 104 end
44 end 105 end
45 local output 106 input = _with_0
46 local _with_1 = io.open(tostring(outputFolder) .. "/" .. tostring(compiledFile), "w+") 107 local _close_0 <close> = input
47 _with_1:write(table.concat(codes))
48 output = _with_1
49 local _close_0 <close> = output
50 end 108 end
51 input = _with_0 109 local output
52 local _close_0 <close> = input 110 local _with_0 = io.open(tostring(outputFolder) .. "/" .. tostring(compiledFile), "w+")
111 _with_0:write(table.concat(codes))
112 output = _with_0
113 local _close_0 <close> = output
53end 114end