aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdoc/docs/doc/README.md22
-rwxr-xr-xdoc/docs/zh/doc/README.md22
-rw-r--r--spec/inputs/assign.yue2
-rw-r--r--spec/inputs/compile_doc.yue4
-rw-r--r--spec/inputs/cond.yue28
-rw-r--r--spec/inputs/destructure.yue8
-rw-r--r--spec/inputs/existential.yue2
-rw-r--r--spec/inputs/macro_teal.yue2
-rw-r--r--spec/inputs/pipe.yue2
-rw-r--r--spec/inputs/plus.yue8
-rw-r--r--spec/inputs/try_catch.yue4
-rw-r--r--spec/inputs/unicode/assign.yue2
-rw-r--r--spec/inputs/unicode/cond.yue28
-rw-r--r--spec/inputs/unicode/destructure.yue8
-rw-r--r--spec/inputs/unicode/existential.yue2
-rw-r--r--spec/inputs/unicode/pipe.yue2
-rw-r--r--spec/inputs/unicode/plus.yue8
-rw-r--r--spec/inputs/unicode/try_catch.yue4
-rw-r--r--src/yuescript/yue_ast.h7
-rw-r--r--src/yuescript/yue_compiler.cpp23
-rw-r--r--src/yuescript/yue_parser.cpp9
-rw-r--r--src/yuescript/yue_parser.h1
22 files changed, 104 insertions, 94 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
index 54c6b72..041120b 100755
--- a/doc/docs/doc/README.md
+++ b/doc/docs/doc/README.md
@@ -1225,32 +1225,32 @@ We know each element in the array table is a two item tuple, so we can unpack it
1225 1225
1226## If Assignment 1226## If Assignment
1227 1227
1228if 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. 1228`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.
1229 1229
1230```moonscript 1230```moonscript
1231if user = database.find_user "moon" 1231if user := database.find_user "moon"
1232 print user.name 1232 print user.name
1233``` 1233```
1234<YueDisplay> 1234<YueDisplay>
1235<pre> 1235<pre>
1236if user = database.find_user "moon" 1236if user := database.find_user "moon"
1237 print user.name 1237 print user.name
1238</pre> 1238</pre>
1239</YueDisplay> 1239</YueDisplay>
1240 1240
1241```moonscript 1241```moonscript
1242if hello = os.getenv "hello" 1242if hello := os.getenv "hello"
1243 print "You have hello", hello 1243 print "You have hello", hello
1244elseif world = os.getenv "world" 1244elseif world := os.getenv "world"
1245 print "you have world", world 1245 print "you have world", world
1246else 1246else
1247 print "nothing :(" 1247 print "nothing :("
1248``` 1248```
1249<YueDisplay> 1249<YueDisplay>
1250<pre> 1250<pre>
1251if hello = os.getenv "hello" 1251if hello := os.getenv "hello"
1252 print "You have hello", hello 1252 print "You have hello", hello
1253elseif world = os.getenv "world" 1253elseif world := os.getenv "world"
1254 print "you have world", world 1254 print "you have world", world
1255else 1255else
1256 print "nothing :(" 1256 print "nothing :("
@@ -1259,13 +1259,13 @@ else
1259 1259
1260If assignment with multiple return values. Only the first value is getting checked, other values are scoped. 1260If assignment with multiple return values. Only the first value is getting checked, other values are scoped.
1261```moonscript 1261```moonscript
1262if success, result = pcall -> "get result without problems" 1262if success, result := pcall -> "get result without problems"
1263 print result -- variable result is scoped 1263 print result -- variable result is scoped
1264print "OK" 1264print "OK"
1265``` 1265```
1266<YueDisplay> 1266<YueDisplay>
1267<pre> 1267<pre>
1268if success, result = pcall -> "get result without problems" 1268if success, result := pcall -> "get result without problems"
1269 print result -- variable result is scoped 1269 print result -- variable result is scoped
1270print "OK" 1270print "OK"
1271</pre> 1271</pre>
@@ -1374,7 +1374,7 @@ try
1374 func 1, 2, 3 1374 func 1, 2, 3
1375 1375
1376-- working with if assignment pattern 1376-- working with if assignment pattern
1377if success, result = try func 1, 2, 3 1377if success, result := try func 1, 2, 3
1378catch err 1378catch err
1379 print yue.traceback err 1379 print yue.traceback err
1380 print result 1380 print result
@@ -1402,7 +1402,7 @@ try
1402 func 1, 2, 3 1402 func 1, 2, 3
1403 1403
1404-- working with if assignment pattern 1404-- working with if assignment pattern
1405if success, result = try func 1, 2, 3 1405if success, result := try func 1, 2, 3
1406catch err 1406catch err
1407 print yue.traceback err 1407 print yue.traceback err
1408 print result 1408 print result
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md
index 7e17b80..a856e7b 100755
--- a/doc/docs/zh/doc/README.md
+++ b/doc/docs/zh/doc/README.md
@@ -1223,32 +1223,32 @@ for [left, right] in *tuples
1223 1223
1224## If 赋值 1224## If 赋值
1225 1225
1226`if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。 1226`if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。注意,你必须使用“海象运算符” `:=` 而不是 `=` 来做赋值。
1227 1227
1228```moonscript 1228```moonscript
1229if user = database.find_user "moon" 1229if user := database.find_user "moon"
1230 print user.name 1230 print user.name
1231``` 1231```
1232<YueDisplay> 1232<YueDisplay>
1233<pre> 1233<pre>
1234if user = database.find_user "moon" 1234if user := database.find_user "moon"
1235 print user.name 1235 print user.name
1236</pre> 1236</pre>
1237</YueDisplay> 1237</YueDisplay>
1238 1238
1239```moonscript 1239```moonscript
1240if hello = os.getenv "hello" 1240if hello := os.getenv "hello"
1241 print "你有 hello", hello 1241 print "你有 hello", hello
1242elseif world = os.getenv "world" 1242elseif world := os.getenv "world"
1243 print "你有 world", world 1243 print "你有 world", world
1244else 1244else
1245 print "什么都没有 :(" 1245 print "什么都没有 :("
1246``` 1246```
1247<YueDisplay> 1247<YueDisplay>
1248<pre> 1248<pre>
1249if hello = os.getenv "hello" 1249if hello := os.getenv "hello"
1250 print "你有 hello", hello 1250 print "你有 hello", hello
1251elseif world = os.getenv "world" 1251elseif world := os.getenv "world"
1252 print "你有 world", world 1252 print "你有 world", world
1253else 1253else
1254 print "什么都没有 :(" 1254 print "什么都没有 :("
@@ -1257,13 +1257,13 @@ else
1257 1257
1258使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。 1258使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。
1259```moonscript 1259```moonscript
1260if success, result = pcall -> "无报错地获取结果" 1260if success, result := pcall -> "无报错地获取结果"
1261 print result -- 变量 result 是有作用域的 1261 print result -- 变量 result 是有作用域的
1262print "好的" 1262print "好的"
1263``` 1263```
1264<YueDisplay> 1264<YueDisplay>
1265<pre> 1265<pre>
1266if success, result = pcall -> "无报错地获取结果" 1266if success, result := pcall -> "无报错地获取结果"
1267 print result -- 变量 result 是有作用域的 1267 print result -- 变量 result 是有作用域的
1268print "好的" 1268print "好的"
1269</pre> 1269</pre>
@@ -1372,7 +1372,7 @@ try
1372 func 1, 2, 3 1372 func 1, 2, 3
1373 1373
1374-- 使用if赋值模式 1374-- 使用if赋值模式
1375if success, result = try func 1, 2, 3 1375if success, result := try func 1, 2, 3
1376catch err 1376catch err
1377 print yue.traceback err 1377 print yue.traceback err
1378 print result 1378 print result
@@ -1400,7 +1400,7 @@ try
1400 func 1, 2, 3 1400 func 1, 2, 3
1401 1401
1402-- 使用if赋值模式 1402-- 使用if赋值模式
1403if success, result = try func 1, 2, 3 1403if success, result := try func 1, 2, 3
1404catch err 1404catch err
1405 print yue.traceback err 1405 print yue.traceback err
1406 print result 1406 print result
diff --git a/spec/inputs/assign.yue b/spec/inputs/assign.yue
index 8ae5cac..2c89a99 100644
--- a/spec/inputs/assign.yue
+++ b/spec/inputs/assign.yue
@@ -30,7 +30,7 @@ c, d = 1, 2 if true
30 30
31x = (do 31x = (do
32 f! 32 f!
33 123) if f = getHandler! 33 123) if f := getHandler!
34 34
35(using nil) <- _ 35(using nil) <- _
36 36
diff --git a/spec/inputs/compile_doc.yue b/spec/inputs/compile_doc.yue
index 4ce2b13..64d7d40 100644
--- a/spec/inputs/compile_doc.yue
+++ b/spec/inputs/compile_doc.yue
@@ -8,13 +8,13 @@ for [compiledFile, docFile] in *[
8 text = \read "*a" 8 text = \read "*a"
9 codes = [] 9 codes = []
10 for code in text\gmatch "```moonscript(.-)```" 10 for code in text\gmatch "```moonscript(.-)```"
11 if result, err = to_lua code, implicit_return_root: false, reserve_line_number: false 11 if result, err := to_lua code, implicit_return_root: false, reserve_line_number: false
12 codes[] = result 12 codes[] = result
13 elseif not err\match "macro exporting module only accepts macro definition" 13 elseif not err\match "macro exporting module only accepts macro definition"
14 print err 14 print err
15 os.exit 1 15 os.exit 1
16 for code in text\gmatch "<pre>(.-)</pre>" 16 for code in text\gmatch "<pre>(.-)</pre>"
17 if result, err = to_lua code\gsub("&lt;", "<")\gsub("&gt;", ">"), implicit_return_root: false, reserve_line_number: false 17 if result, err := to_lua code\gsub("&lt;", "<")\gsub("&gt;", ">"), implicit_return_root: false, reserve_line_number: false
18 codes[] = result 18 codes[] = result
19 else 19 else
20 print err 20 print err
diff --git a/spec/inputs/cond.yue b/spec/inputs/cond.yue
index 5bc6c9b..cce96df 100644
--- a/spec/inputs/cond.yue
+++ b/spec/inputs/cond.yue
@@ -52,18 +52,18 @@ elseif "just us"
52 52
53-- 53--
54 54
55if something = 10 55if something := 10
56 print something 56 print something
57else 57else
58 print "else" 58 print "else"
59 59
60hello = if something = 10 60hello = if something := 10
61 print something 61 print something
62else 62else
63 print "else" 63 print "else"
64 64
65 65
66hello = 5 + if something = 10 66hello = 5 + if something := 10
67 print something 67 print something
68 68
69--- 69---
@@ -72,9 +72,9 @@ z = false
72 72
73_ = if false 73_ = if false
74 one 74 one
75elseif x = true 75elseif x := true
76 two 76 two
77elseif z = true 77elseif z := true
78 three 78 three
79else 79else
80 four 80 four
@@ -82,17 +82,17 @@ else
82 82
83out = if false 83out = if false
84 one 84 one
85elseif x = true 85elseif x := true
86 two 86 two
87elseif z = true 87elseif z := true
88 three 88 three
89else 89else
90 four 90 four
91 91
92kzy = -> 92kzy = ->
93 if something = true 93 if something := true
94 1 94 1
95 elseif another = false 95 elseif another := false
96 2 96 2
97 97
98--- 98---
@@ -152,7 +152,7 @@ dddd = {1,2,3} unless value
152 152
153do 153do
154 j = 100 154 j = 100
155 unless j = hi! 155 unless j := hi!
156 error "not j!" 156 error "not j!"
157 157
158---------------- 158----------------
@@ -200,22 +200,22 @@ do
200 elseif c 200 elseif c
201 d: e = tb 201 d: e = tb
202 202
203if :pi = math 203if :pi := math
204 print pi 204 print pi
205 205
206do 206do
207 local math 207 local math
208 if :pi = math 208 if :pi := math
209 print pi 209 print pi
210 210
211do 211do
212 if _M = {} 212 if _M := {}
213 :Thing = _M 213 :Thing = _M
214 :a, :b = _M 214 :a, :b = _M
215 215
216do 216do
217 global _M 217 global _M
218 if _M = {} 218 if _M := {}
219 :Thing = _M 219 :Thing = _M
220 :a, :b = _M 220 :a, :b = _M
221 221
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue
index 73e4d33..5017ee1 100644
--- a/spec/inputs/destructure.yue
+++ b/spec/inputs/destructure.yue
@@ -94,18 +94,18 @@ do
94 94
95do 95do
96 thing = nil 96 thing = nil
97 if {a} = thing 97 if {a} := thing
98 print a 98 print a
99 else 99 else
100 print "nothing" 100 print "nothing"
101 101
102 thang = {1,2} 102 thang = {1,2}
103 if {a,b} = thang 103 if {a,b} := thang
104 print a,b 104 print a,b
105 105
106 if {a,b} = thing 106 if {a,b} := thing
107 print a,b 107 print a,b
108 elseif {c,d} = thang 108 elseif {c,d} := thang
109 print c,d 109 print c,d
110 else 110 else
111 print "NO" 111 print "NO"
diff --git a/spec/inputs/existential.yue b/spec/inputs/existential.yue
index 27891dc..ec38897 100644
--- a/spec/inputs/existential.yue
+++ b/spec/inputs/existential.yue
@@ -16,7 +16,7 @@ with abc?!\func?!
16 if \p? "abc" 16 if \p? "abc"
17 return 123 17 return 123
18 18
19if {:x} = a?.if?\then?(123)? @?\function 998 19if {:x} := a?.if?\then?(123)? @?\function 998
20 print x 20 print x
21 21
22res = b.function\do!\while?("OK")\if("def",998)\f? 22res = b.function\do!\while?("OK")\if("def",998)\f?
diff --git a/spec/inputs/macro_teal.yue b/spec/inputs/macro_teal.yue
index a443614..0cfd862 100644
--- a/spec/inputs/macro_teal.yue
+++ b/spec/inputs/macro_teal.yue
@@ -8,7 +8,7 @@ macro to_lua = (code)->
8 "require('yue').to_lua(#{code}, reserve_line_number:false, same_module:true)" 8 "require('yue').to_lua(#{code}, reserve_line_number:false, same_module:true)"
9 9
10macro trim = (name)-> 10macro trim = (name)->
11 "if result = #{name}\\match '[\\'\"](.*)[\\'\"]' then result else #{name}" 11 "if result := #{name}\\match '[\\'\"](.*)[\\'\"]' then result else #{name}"
12 12
13export macro local = (decl, value = nil)-> 13export macro local = (decl, value = nil)->
14 import "yue" as {options:{:tl_enabled}} 14 import "yue" as {options:{:tl_enabled}}
diff --git a/spec/inputs/pipe.yue b/spec/inputs/pipe.yue
index 02f87a3..b5bae1d 100644
--- a/spec/inputs/pipe.yue
+++ b/spec/inputs/pipe.yue
@@ -11,7 +11,7 @@
11 11
12b = 1 + 2 + (4 |> tostring |> print(1) or 123) 12b = 1 + 2 + (4 |> tostring |> print(1) or 123)
13 13
14if x = 233 |> math.max 998 14if x := 233 |> math.max 998
15 print x 15 print x
16 16
17with b |> create? "new" 17with b |> create? "new"
diff --git a/spec/inputs/plus.yue b/spec/inputs/plus.yue
index e387090..9c500a4 100644
--- a/spec/inputs/plus.yue
+++ b/spec/inputs/plus.yue
@@ -8,13 +8,13 @@ c.repeat.if\then("xyz")\else res
8 8
9print @for,@@function 123 9print @for,@@function 123
10 10
11if fcolor = message\match "<%w*>" then message = message\gsub "<%->", fcolor 11if fcolor := message\match "<%w*>" then message = message\gsub "<%->", fcolor
12 12
13message = message\gsub "<%->", fcolor if fcolor = message\match "<%w*>" 13message = message\gsub "<%->", fcolor if fcolor := message\match "<%w*>"
14 14
15valA = func! if func = getfunc! 15valA = func! if func := getfunc!
16 16
17local valA = func! if func = getfunc! 17local valA = func! if func := getfunc!
18 18
19valB = do 19valB = do
20 func = getfunc! 20 func = getfunc!
diff --git a/spec/inputs/try_catch.yue b/spec/inputs/try_catch.yue
index 96a87fc..ccb3f52 100644
--- a/spec/inputs/try_catch.yue
+++ b/spec/inputs/try_catch.yue
@@ -39,14 +39,14 @@ catch err
39 print "OK" 39 print "OK"
40 40
41do 41do
42 if success, result = try func "abc", 123 42 if success, result := try func "abc", 123
43 print result 43 print result
44 44
45 success, result = try func "abc", 123 45 success, result = try func "abc", 123
46 catch err 46 catch err
47 print err 47 print err
48 48
49 print result if success, result = try func "abc", 123 49 print result if success, result := try func "abc", 123
50 catch err 50 catch err
51 print err 51 print err
52 52
diff --git a/spec/inputs/unicode/assign.yue b/spec/inputs/unicode/assign.yue
index 5392a92..6c03f86 100644
--- a/spec/inputs/unicode/assign.yue
+++ b/spec/inputs/unicode/assign.yue
@@ -30,7 +30,7 @@ else
30 30
31变量x = (do 31变量x = (do
32 函数! 32 函数!
33 123) if 函数 = 获取处理函数! 33 123) if 函数 := 获取处理函数!
34 34
35(using nil) <- _无效变量 35(using nil) <- _无效变量
36 36
diff --git a/spec/inputs/unicode/cond.yue b/spec/inputs/unicode/cond.yue
index fca6d60..dde5c99 100644
--- a/spec/inputs/unicode/cond.yue
+++ b/spec/inputs/unicode/cond.yue
@@ -52,18 +52,18 @@ elseif "只有我们"
52 52
53-- 53--
54 54
55if 某东西 = 10 55if 某东西 := 10
56 打印 某东西 56 打印 某东西
57else 57else
58 打印 "其它" 58 打印 "其它"
59 59
60你好 = if 某东西 = 10 60你好 = if 某东西 := 10
61 打印 某东西 61 打印 某东西
62else 62else
63 打印 "其它" 63 打印 "其它"
64 64
65 65
66你好 = 5 + if 某东西 = 10 66你好 = 5 + if 某东西 := 10
67 打印 某东西 67 打印 某东西
68 68
69--- 69---
@@ -72,9 +72,9 @@ z变量 = false
72 72
73_无效变量 = if false 73_无效变量 = if false
74 74
75elseif 条件x = true 75elseif 条件x := true
76 76
77elseif 条件z = true 77elseif 条件z := true
78 78
79else 79else
80 80
@@ -82,17 +82,17 @@ else
82 82
83输出 = if false 83输出 = if false
84 84
85elseif 条件x = true 85elseif 条件x := true
86 86
87elseif 条件z = true 87elseif 条件z := true
88 88
89else 89else
90 90
91 91
92变量 = -> 92变量 = ->
93 if 某东西 = true 93 if 某东西 := true
94 1 94 1
95 elseif 另一个 = false 95 elseif 另一个 := false
96 2 96 2
97 97
98--- 98---
@@ -152,7 +152,7 @@ else
152 152
153do 153do
154 j变量 = 100 154 j变量 = 100
155 unless j变量 = 嗨! 155 unless j变量 := 嗨!
156 错误 "不是 j变量!" 156 错误 "不是 j变量!"
157 157
158---------------- 158----------------
@@ -200,22 +200,22 @@ do
200 elseif 条件c 200 elseif 条件c
201 字段d: 变量e = 变量tb 201 字段d: 变量e = 变量tb
202 202
203if :派 = 数学库 203if :派 := 数学库
204 打印 派 204 打印 派
205 205
206do 206do
207 local 数学库 207 local 数学库
208 if :派 = 数学库 208 if :派 := 数学库
209 打印 派 209 打印 派
210 210
211do 211do
212 if _模块 = {} 212 if _模块 := {}
213 :东西 = _模块 213 :东西 = _模块
214 :a功能, :b功能 = _模块 214 :a功能, :b功能 = _模块
215 215
216do 216do
217 global _模块 217 global _模块
218 if _模块 = {} 218 if _模块 := {}
219 :东西 = _模块 219 :东西 = _模块
220 :a功能, :b功能 = _模块 220 :a功能, :b功能 = _模块
221 221
diff --git a/spec/inputs/unicode/destructure.yue b/spec/inputs/unicode/destructure.yue
index 5efdf82..3c3a369 100644
--- a/spec/inputs/unicode/destructure.yue
+++ b/spec/inputs/unicode/destructure.yue
@@ -92,18 +92,18 @@ do
92 92
93do 93do
94 东西 = nil 94 东西 = nil
95 if {元素a} = 东西 95 if {元素a} := 东西
96 打印 元素a 96 打印 元素a
97 else 97 else
98 打印 "没东西" 98 打印 "没东西"
99 99
100 东东 = {1,2} 100 东东 = {1,2}
101 if {元素a,元素b} = 东东 101 if {元素a,元素b} := 东东
102 打印 元素a,元素b 102 打印 元素a,元素b
103 103
104 if {元素a,元素b} = 东西 104 if {元素a,元素b} := 东西
105 打印 元素a,元素b 105 打印 元素a,元素b
106 elseif {元素c,元素d} = 东东 106 elseif {元素c,元素d} := 东东
107 打印 元素c,元素d 107 打印 元素c,元素d
108 else 108 else
109 打印 "不" 109 打印 "不"
diff --git a/spec/inputs/unicode/existential.yue b/spec/inputs/unicode/existential.yue
index 0e35a39..de65027 100644
--- a/spec/inputs/unicode/existential.yue
+++ b/spec/inputs/unicode/existential.yue
@@ -16,7 +16,7 @@ with 对象abc?!\函数?!
16 if \函数p? "abc" 16 if \函数p? "abc"
17 return 123 17 return 123
18 18
19if {:x字段} = 对象a?.如果?\然后?(123)? @?\方法 998 19if {:x字段} := 对象a?.如果?\然后?(123)? @?\方法 998
20 打印 x字段 20 打印 x字段
21 21
22结果 = 对象b.方法\执行!\当?("没问题")\如果("默认",998)\函数? 22结果 = 对象b.方法\执行!\当?("没问题")\如果("默认",998)\函数?
diff --git a/spec/inputs/unicode/pipe.yue b/spec/inputs/unicode/pipe.yue
index 2cd41ee..085a2cf 100644
--- a/spec/inputs/unicode/pipe.yue
+++ b/spec/inputs/unicode/pipe.yue
@@ -11,7 +11,7 @@
11 11
12变量b = 1 + 2 + (4 |> tostring |> 打印(1) or 123) 12变量b = 1 + 2 + (4 |> tostring |> 打印(1) or 123)
13 13
14if 变量x = 233 |> math.max 998 14if 变量x := 233 |> math.max 998
15 打印 变量x 15 打印 变量x
16 16
17with 变量b |> 创建? "new" 17with 变量b |> 创建? "new"
diff --git a/spec/inputs/unicode/plus.yue b/spec/inputs/unicode/plus.yue
index b08974f..70b57bb 100644
--- a/spec/inputs/unicode/plus.yue
+++ b/spec/inputs/unicode/plus.yue
@@ -8,13 +8,13 @@
8 8
9打印 @循环, @@函数 123 9打印 @循环, @@函数 123
10 10
11if 颜色 = 消息\匹配 "<%w*>" then 消息 = 消息\替换 "<%->", 颜色 11if 颜色 := 消息\匹配 "<%w*>" then 消息 = 消息\替换 "<%->", 颜色
12 12
13消息 = 消息\替换 "<%->", 颜色 if 颜色 = 消息\匹配 "<%w*>" 13消息 = 消息\替换 "<%->", 颜色 if 颜色 := 消息\匹配 "<%w*>"
14 14
15数值A = 方法! if 方法 = 获取方法! 15数值A = 方法! if 方法 := 获取方法!
16 16
17local 数值A = 方法! if 方法 = 获取方法! 17local 数值A = 方法! if 方法 := 获取方法!
18 18
19数值B = do 19数值B = do
20 方法 = 获取方法! 20 方法 = 获取方法!
diff --git a/spec/inputs/unicode/try_catch.yue b/spec/inputs/unicode/try_catch.yue
index 71e03ee..1156d8e 100644
--- a/spec/inputs/unicode/try_catch.yue
+++ b/spec/inputs/unicode/try_catch.yue
@@ -39,14 +39,14 @@ catch 错误
39 打印 "好的" 39 打印 "好的"
40 40
41do 41do
42 if 成功, 结果 = try 函数 "abc", 123 42 if 成功, 结果 := try 函数 "abc", 123
43 打印 结果 43 打印 结果
44 44
45 成功, 结果 = try 函数 "abc", 123 45 成功, 结果 = try 函数 "abc", 123
46 catch 错误 46 catch 错误
47 打印 错误 47 打印 错误
48 48
49 打印 结果 if 成功, 结果 = try 函数 "abc", 123 49 打印 结果 if 成功, 结果 := try 函数 "abc", 123
50 catch 错误 50 catch 错误
51 打印 错误 51 打印 错误
52 52
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index fa47559..6b2b7f8 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -302,14 +302,15 @@ AST_NODE(Switch)
302AST_END(Switch, "switch"sv) 302AST_END(Switch, "switch"sv)
303 303
304AST_NODE(Assignment) 304AST_NODE(Assignment)
305 ast_ptr<true, ExpList_t> expList; 305 ast_ptr<false, ExpList_t> expList;
306 ast_ptr<true, Assign_t> assign; 306 ast_ptr<true, Assign_t> assign;
307 AST_MEMBER(Assignment, &expList, &assign) 307 AST_MEMBER(Assignment, &expList, &assign)
308AST_END(Assignment, "assignment"sv) 308AST_END(Assignment, "assignment"sv)
309 309
310AST_NODE(IfCond) 310AST_NODE(IfCond)
311 ast_sel<true, Exp_t, Assignment_t> condition; 311 ast_ptr<true, Exp_t> condition;
312 AST_MEMBER(IfCond, &condition) 312 ast_ptr<false, Assignment_t> assignment;
313 AST_MEMBER(IfCond, &condition, &assignment)
313AST_END(IfCond, "if_cond"sv) 314AST_END(IfCond, "if_cond"sv)
314 315
315AST_LEAF(IfType) 316AST_LEAF(IfType)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 69a028f..d37f911 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
75 "close"s // Lua 5.4 75 "close"s // Lua 5.4
76}; 76};
77 77
78const std::string_view version = "0.20.7"sv; 78const std::string_view version = "0.21.0"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class CompileError : public std::logic_error {
@@ -3088,7 +3088,7 @@ private:
3088 for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) { 3088 for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) {
3089 ns.push_back(*it); 3089 ns.push_back(*it);
3090 if (auto cond = ast_cast<IfCond_t>(*it)) { 3090 if (auto cond = ast_cast<IfCond_t>(*it)) {
3091 if (*it != nodes.front() && cond->condition.is<Assignment_t>()) { 3091 if (*it != nodes.front() && cond->assignment) {
3092 auto x = *it; 3092 auto x = *it;
3093 auto newIf = x->new_ptr<If_t>(); 3093 auto newIf = x->new_ptr<If_t>();
3094 newIf->type.set(toAst<IfType_t>("if"sv, x)); 3094 newIf->type.set(toAst<IfType_t>("if"sv, x));
@@ -3142,11 +3142,12 @@ private:
3142 default: YUEE("AST node mismatch", node); break; 3142 default: YUEE("AST node mismatch", node); break;
3143 } 3143 }
3144 } 3144 }
3145 auto asmt = ifCondPairs.front().first->condition.as<Assignment_t>(); 3145 auto firstIfCond = ifCondPairs.front().first;
3146 auto asmt = firstIfCond->assignment.get();
3146 bool storingValue = false; 3147 bool storingValue = false;
3147 ast_ptr<false, ExpListAssign_t> extraAssignment; 3148 ast_ptr<false, ExpListAssign_t> extraAssignment;
3148 if (asmt) { 3149 if (asmt) {
3149 ast_ptr<false, ast_node> exp = asmt->expList->exprs.front(); 3150 auto exp = firstIfCond->condition.get();
3150 auto x = exp; 3151 auto x = exp;
3151 auto var = singleVariableFrom(exp, false); 3152 auto var = singleVariableFrom(exp, false);
3152 if (var.empty() || isGlobal(var)) { 3153 if (var.empty() || isGlobal(var)) {
@@ -3164,11 +3165,12 @@ private:
3164 temp.push_back(indent() + "do"s + nll(asmt)); 3165 temp.push_back(indent() + "do"s + nll(asmt));
3165 pushScope(); 3166 pushScope();
3166 } 3167 }
3167 asmt->expList->exprs.pop_front();
3168 auto expList = toAst<ExpList_t>(desVar, x); 3168 auto expList = toAst<ExpList_t>(desVar, x);
3169 auto assignment = x->new_ptr<ExpListAssign_t>(); 3169 auto assignment = x->new_ptr<ExpListAssign_t>();
3170 for (auto expr : asmt->expList->exprs.objects()) { 3170 if (asmt->expList) {
3171 expList->exprs.push_back(expr); 3171 for (auto expr : asmt->expList->exprs.objects()) {
3172 expList->exprs.push_back(expr);
3173 }
3172 } 3174 }
3173 assignment->expList.set(expList); 3175 assignment->expList.set(expList);
3174 assignment->action.set(asmt->assign); 3176 assignment->action.set(asmt->assign);
@@ -3196,9 +3198,10 @@ private:
3196 } 3198 }
3197 auto expList = x->new_ptr<ExpList_t>(); 3199 auto expList = x->new_ptr<ExpList_t>();
3198 expList->exprs.push_back(exp); 3200 expList->exprs.push_back(exp);
3199 asmt->expList->exprs.pop_front(); 3201 if (asmt->expList) {
3200 for (auto expr : asmt->expList->exprs.objects()) { 3202 for (auto expr : asmt->expList->exprs.objects()) {
3201 expList->exprs.push_back(expr); 3203 expList->exprs.push_back(expr);
3204 }
3202 } 3205 }
3203 auto assignment = x->new_ptr<ExpListAssign_t>(); 3206 auto assignment = x->new_ptr<ExpListAssign_t>();
3204 assignment->expList.set(expList); 3207 assignment->expList.set(expList);
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 2206686..5b97a25 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -114,6 +114,11 @@ YueParser::YueParser() {
114 return false; 114 return false;
115 }); 115 });
116 116
117 if_assignment_syntax_error = pl::user(true_(), [](const item_t& item) {
118 throw ParserError("use := for if-assignment expression"sv, item.begin);
119 return false;
120 });
121
117 #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut) 122 #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut)
118 123
119 #define key(str) (expr(str) >> not_alpha_num) 124 #define key(str) (expr(str) >> not_alpha_num)
@@ -369,8 +374,8 @@ YueParser::YueParser() {
369 +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent 374 +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent
370 ) >> switch_block; 375 ) >> switch_block;
371 376
372 Assignment = ExpList >> space >> Assign; 377 Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error);
373 IfCond = disable_chain_rule(disable_arg_table_block_rule(Assignment | Exp)); 378 IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment)));
374 if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); 379 if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then");
375 if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; 380 if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body;
376 IfType = (expr("if") | "unless") >> not_alpha_num; 381 IfType = (expr("if") | "unless") >> not_alpha_num;
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 16b57b2..c3d5d7d 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -141,6 +141,7 @@ private:
141 NONE_AST_RULE(invalid_interpolation_error); 141 NONE_AST_RULE(invalid_interpolation_error);
142 NONE_AST_RULE(confusing_unary_not_error); 142 NONE_AST_RULE(confusing_unary_not_error);
143 NONE_AST_RULE(table_key_pair_error); 143 NONE_AST_RULE(table_key_pair_error);
144 NONE_AST_RULE(if_assignment_syntax_error);
144 145
145 NONE_AST_RULE(inc_exp_level); 146 NONE_AST_RULE(inc_exp_level);
146 NONE_AST_RULE(dec_exp_level); 147 NONE_AST_RULE(dec_exp_level);