diff options
| author | Li Jin <dragon-fly@qq.com> | 2025-05-26 11:07:38 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2025-05-26 11:07:38 +0800 |
| commit | a91135ce512f907ed085d9aac147d8fcad356406 (patch) | |
| tree | e53408fe0a88ef71ea33d14bcb0b6eeb3a344810 | |
| parent | 4ba4c90e711c6204aa40e38347c5a5a076d9370e (diff) | |
| download | yuescript-a91135ce512f907ed085d9aac147d8fcad356406.tar.gz yuescript-a91135ce512f907ed085d9aac147d8fcad356406.tar.bz2 yuescript-a91135ce512f907ed085d9aac147d8fcad356406.zip | |
Added assignment expression for switch syntax.
| -rwxr-xr-x | doc/docs/doc/README.md | 16 | ||||
| -rwxr-xr-x | doc/docs/zh/doc/README.md | 16 | ||||
| -rw-r--r-- | spec/inputs/destructure.yue | 2 | ||||
| -rw-r--r-- | spec/inputs/macro_export.yue | 4 | ||||
| -rw-r--r-- | spec/inputs/switch.yue | 54 | ||||
| -rw-r--r-- | spec/inputs/unicode/destructure.yue | 2 | ||||
| -rw-r--r-- | spec/inputs/unicode/macro_export.yue | 4 | ||||
| -rw-r--r-- | spec/inputs/unicode/with.yue | 24 | ||||
| -rw-r--r-- | spec/inputs/with.yue | 24 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc.lua | 4 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc_zh.lua | 4 | ||||
| -rw-r--r-- | spec/outputs/switch.lua | 71 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.cpp | 7 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 19 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 32 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 11 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 2 |
17 files changed, 218 insertions, 78 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md index 58b37c0..7e9b454 100755 --- a/doc/docs/doc/README.md +++ b/doc/docs/doc/README.md | |||
| @@ -2696,28 +2696,26 @@ reader\parse_line! until reader\eof! | |||
| 2696 | 2696 | ||
| 2697 | ## Switch | 2697 | ## Switch |
| 2698 | 2698 | ||
| 2699 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. | 2699 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. In switch statement, you can also use assignment expression to store temporary variable value. |
| 2700 | 2700 | ||
| 2701 | ```moonscript | 2701 | ```moonscript |
| 2702 | name = "Dan" | 2702 | switch name := "Dan" |
| 2703 | switch name | ||
| 2704 | when "Robert" | 2703 | when "Robert" |
| 2705 | print "You are Robert" | 2704 | print "You are Robert" |
| 2706 | when "Dan", "Daniel" | 2705 | when "Dan", "Daniel" |
| 2707 | print "Your name, it's Dan" | 2706 | print "Your name, it's Dan" |
| 2708 | else | 2707 | else |
| 2709 | print "I don't know about your name" | 2708 | print "I don't know about you with name #{name}" |
| 2710 | ``` | 2709 | ``` |
| 2711 | <YueDisplay> | 2710 | <YueDisplay> |
| 2712 | <pre> | 2711 | <pre> |
| 2713 | name = "Dan" | 2712 | switch name := "Dan" |
| 2714 | switch name | ||
| 2715 | when "Robert" | 2713 | when "Robert" |
| 2716 | print "You are Robert" | 2714 | print "You are Robert" |
| 2717 | when "Dan", "Daniel" | 2715 | when "Dan", "Daniel" |
| 2718 | print "Your name, it's Dan" | 2716 | print "Your name, it's Dan" |
| 2719 | else | 2717 | else |
| 2720 | print "I don't know about your name" | 2718 | print "I don't know about you with name #{name}" |
| 2721 | </pre> | 2719 | </pre> |
| 2722 | </YueDisplay> | 2720 | </YueDisplay> |
| 2723 | 2721 | ||
| @@ -3528,13 +3526,13 @@ In this usage, with can be seen as a special form of the K combinator. | |||
| 3528 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. | 3526 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. |
| 3529 | 3527 | ||
| 3530 | ```moonscript | 3528 | ```moonscript |
| 3531 | with str = "Hello" | 3529 | with str := "Hello" |
| 3532 | print "original:", str | 3530 | print "original:", str |
| 3533 | print "upper:", \upper! | 3531 | print "upper:", \upper! |
| 3534 | ``` | 3532 | ``` |
| 3535 | <YueDisplay> | 3533 | <YueDisplay> |
| 3536 | <pre> | 3534 | <pre> |
| 3537 | with str = "Hello" | 3535 | with str := "Hello" |
| 3538 | print "original:", str | 3536 | print "original:", str |
| 3539 | print "upper:", \upper! | 3537 | print "upper:", \upper! |
| 3540 | </pre> | 3538 | </pre> |
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md index 1dd59a7..da90fa6 100755 --- a/doc/docs/zh/doc/README.md +++ b/doc/docs/zh/doc/README.md | |||
| @@ -2655,28 +2655,26 @@ reader\parse_line! until reader\eof! | |||
| 2655 | 2655 | ||
| 2656 | ## switch 语句 | 2656 | ## switch 语句 |
| 2657 | 2657 | ||
| 2658 | switch语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和if语句一样,switch语句在最后可以接一个else代码块来处理没有匹配的情况。在生成的Lua代码中,进行比较是使用==操作符完成的。 | 2658 | switch语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和if语句一样,switch语句在最后可以接一个else代码块来处理没有匹配的情况。在生成的Lua代码中,进行比较是使用==操作符完成的。switch语句中也可以使用赋值表达式来储存临时变量值。 |
| 2659 | 2659 | ||
| 2660 | ```moonscript | 2660 | ```moonscript |
| 2661 | name = "Dan" | 2661 | switch name := "Dan" |
| 2662 | switch name | ||
| 2663 | when "Robert" | 2662 | when "Robert" |
| 2664 | print "你是Robert" | 2663 | print "你是Robert" |
| 2665 | when "Dan", "Daniel" | 2664 | when "Dan", "Daniel" |
| 2666 | print "你的名字是Dan" | 2665 | print "你的名字是Dan" |
| 2667 | else | 2666 | else |
| 2668 | print "我不知道你的名字" | 2667 | print "我不认识你,你的名字是#{name}" |
| 2669 | ``` | 2668 | ``` |
| 2670 | <YueDisplay> | 2669 | <YueDisplay> |
| 2671 | <pre> | 2670 | <pre> |
| 2672 | name = "Dan" | 2671 | switch name := "Dan" |
| 2673 | switch name | ||
| 2674 | when "Robert" | 2672 | when "Robert" |
| 2675 | print "你是Robert" | 2673 | print "你是Robert" |
| 2676 | when "Dan", "Daniel" | 2674 | when "Dan", "Daniel" |
| 2677 | print "你的名字是Dan" | 2675 | print "你的名字是Dan" |
| 2678 | else | 2676 | else |
| 2679 | print "我不知道你的名字" | 2677 | print "我不认识你,你的名字是#{name}" |
| 2680 | </pre> | 2678 | </pre> |
| 2681 | </YueDisplay> | 2679 | </YueDisplay> |
| 2682 | 2680 | ||
| @@ -3484,13 +3482,13 @@ me = create_person "Leaf", [dad, mother, sister] | |||
| 3484 | 如果你想给表达式另外起一个名称的话,with语句中的表达式也可以是一个赋值语句。 | 3482 | 如果你想给表达式另外起一个名称的话,with语句中的表达式也可以是一个赋值语句。 |
| 3485 | 3483 | ||
| 3486 | ```moonscript | 3484 | ```moonscript |
| 3487 | with str = "你好" | 3485 | with str := "你好" |
| 3488 | print "原始:", str | 3486 | print "原始:", str |
| 3489 | print "大写:", \upper! | 3487 | print "大写:", \upper! |
| 3490 | ``` | 3488 | ``` |
| 3491 | <YueDisplay> | 3489 | <YueDisplay> |
| 3492 | <pre> | 3490 | <pre> |
| 3493 | with str = "你好" | 3491 | with str := "你好" |
| 3494 | print "原始:", str | 3492 | print "原始:", str |
| 3495 | print "大写:", \upper! | 3493 | print "大写:", \upper! |
| 3496 | </pre> | 3494 | </pre> |
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 674dfe4..9f01a20 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue | |||
| @@ -94,7 +94,7 @@ do | |||
| 94 | -- | 94 | -- |
| 95 | 95 | ||
| 96 | do | 96 | do |
| 97 | with {a,b} = thing | 97 | with {a,b} := thing |
| 98 | print a, b | 98 | print a, b |
| 99 | 99 | ||
| 100 | 100 | ||
diff --git a/spec/inputs/macro_export.yue b/spec/inputs/macro_export.yue index cc7d459..75fd813 100644 --- a/spec/inputs/macro_export.yue +++ b/spec/inputs/macro_export.yue | |||
| @@ -38,8 +38,8 @@ export macro copy = (src, dst, ...)-> | |||
| 38 | " | 38 | " |
| 39 | do | 39 | do |
| 40 | local _src_, _dst_ | 40 | local _src_, _dst_ |
| 41 | with _dst_ = #{dst} | 41 | with _dst_ := #{dst} |
| 42 | with _src_ = #{src} | 42 | with _src_ := #{src} |
| 43 | #{table.concat for field in *{...} do " | 43 | #{table.concat for field in *{...} do " |
| 44 | _dst_.#{field} = _src_.#{field} | 44 | _dst_.#{field} = _src_.#{field} |
| 45 | "}" | 45 | "}" |
diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue index 7ff3118..5097db3 100644 --- a/spec/inputs/switch.yue +++ b/spec/inputs/switch.yue | |||
| @@ -220,4 +220,56 @@ do | |||
| 220 | ] | 220 | ] |
| 221 | print "matched", sixth | 221 | print "matched", sixth |
| 222 | 222 | ||
| 223 | nil \ No newline at end of file | 223 | do |
| 224 | switch v := "hello" | ||
| 225 | when "hello" | ||
| 226 | print "matched hello" | ||
| 227 | else | ||
| 228 | print "not matched" | ||
| 229 | -- output: matched hello | ||
| 230 | |||
| 231 | do | ||
| 232 | f = -> "ok" | ||
| 233 | switch val := f! | ||
| 234 | when "ok" | ||
| 235 | print "it's ok" | ||
| 236 | -- output: it's ok | ||
| 237 | |||
| 238 | |||
| 239 | do | ||
| 240 | g = -> 42 | ||
| 241 | switch result := g! | ||
| 242 | when 1, 2 | ||
| 243 | print "small" | ||
| 244 | when 42 | ||
| 245 | print "life universe everything" | ||
| 246 | else | ||
| 247 | print "other #{result}" | ||
| 248 | -- output: life universe everything | ||
| 249 | |||
| 250 | do | ||
| 251 | check = -> | ||
| 252 | if true | ||
| 253 | "yes" | ||
| 254 | else | ||
| 255 | "no" | ||
| 256 | |||
| 257 | switch x := check! | ||
| 258 | when "yes" | ||
| 259 | print "affirmative" | ||
| 260 | else | ||
| 261 | print "negative" | ||
| 262 | -- output: affirmative | ||
| 263 | |||
| 264 | do | ||
| 265 | t = (): tb -> | ||
| 266 | tb = {a: 1} | ||
| 267 | tb.a = 2 | ||
| 268 | |||
| 269 | switch data := t! | ||
| 270 | when {a: 2} | ||
| 271 | print "matched" | ||
| 272 | else | ||
| 273 | print "not matched" | ||
| 274 | |||
| 275 | nil | ||
diff --git a/spec/inputs/unicode/destructure.yue b/spec/inputs/unicode/destructure.yue index 3c3a369..a5ffd5d 100644 --- a/spec/inputs/unicode/destructure.yue +++ b/spec/inputs/unicode/destructure.yue | |||
| @@ -84,7 +84,7 @@ do | |||
| 84 | -- | 84 | -- |
| 85 | 85 | ||
| 86 | do | 86 | do |
| 87 | with {元素a,元素b} = 东西 | 87 | with {元素a,元素b} := 东西 |
| 88 | 打印 元素a, 元素b | 88 | 打印 元素a, 元素b |
| 89 | 89 | ||
| 90 | 90 | ||
diff --git a/spec/inputs/unicode/macro_export.yue b/spec/inputs/unicode/macro_export.yue index 3c9a942..56571cd 100644 --- a/spec/inputs/unicode/macro_export.yue +++ b/spec/inputs/unicode/macro_export.yue | |||
| @@ -37,8 +37,8 @@ export macro 复制 = (源, 目标, ...)-> | |||
| 37 | " | 37 | " |
| 38 | do | 38 | do |
| 39 | local _源_, _目标_ | 39 | local _源_, _目标_ |
| 40 | with _目标_ = #{目标} | 40 | with _目标_ := #{目标} |
| 41 | with _源_ = #{源} | 41 | with _源_ := #{源} |
| 42 | #{table.concat for 字段 in *{...} do " | 42 | #{table.concat for 字段 in *{...} do " |
| 43 | _目标_.#{字段} = _源_.#{字段} | 43 | _目标_.#{字段} = _源_.#{字段} |
| 44 | "}" | 44 | "}" |
diff --git a/spec/inputs/unicode/with.yue b/spec/inputs/unicode/with.yue index ecbfdab..3c15add 100644 --- a/spec/inputs/unicode/with.yue +++ b/spec/inputs/unicode/with.yue | |||
| @@ -45,19 +45,19 @@ do | |||
| 45 | with 变量a | 45 | with 变量a |
| 46 | 打印 .世界 | 46 | 打印 .世界 |
| 47 | 47 | ||
| 48 | 模块 = with _模块 = {} | 48 | 模块 = with _模块 := {} |
| 49 | .事物 = "你好" | 49 | .事物 = "你好" |
| 50 | 50 | ||
| 51 | with 变量a, 变量b = 东西, 布 | 51 | with 变量a, 变量b := 东西, 布 |
| 52 | 打印 .世界 | 52 | 打印 .世界 |
| 53 | 53 | ||
| 54 | 变量x = with 变量a, 变量b = 1, 2 | 54 | 变量x = with 变量a, 变量b := 1, 2 |
| 55 | 打印 变量a + 变量b | 55 | 打印 变量a + 变量b |
| 56 | 56 | ||
| 57 | 打印 with 变量a, 变量b = 1, 2 | 57 | 打印 with 变量a, 变量b := 1, 2 |
| 58 | 打印 变量a + 变量b | 58 | 打印 变量a + 变量b |
| 59 | 59 | ||
| 60 | p = with 你好!.字段x, 世界!.字段y = 1, 2 | 60 | p = with 你好!.字段x, 世界!.字段y := 1, 2 |
| 61 | 打印 变量a + 变量b | 61 | 打印 变量a + 变量b |
| 62 | 62 | ||
| 63 | -- | 63 | -- |
| @@ -68,16 +68,16 @@ do | |||
| 68 | 变量x\大写! | 68 | 变量x\大写! |
| 69 | 69 | ||
| 70 | do | 70 | do |
| 71 | with 变量k = "乔" | 71 | with 变量k := "乔" |
| 72 | 打印 \大写! | 72 | 打印 \大写! |
| 73 | 73 | ||
| 74 | do | 74 | do |
| 75 | with 变量a,变量b,变量c = "", "", "" | 75 | with 变量a,变量b,变量c := "", "", "" |
| 76 | 打印 \大写! | 76 | 打印 \大写! |
| 77 | 77 | ||
| 78 | do | 78 | do |
| 79 | 变量a = "床铺" | 79 | 变量a = "床铺" |
| 80 | with 变量a,变量b,变量c = "", "", "" | 80 | with 变量a,变量b,变量c := "", "", "" |
| 81 | 打印 \大写! | 81 | 打印 \大写! |
| 82 | 82 | ||
| 83 | do | 83 | do |
| @@ -85,7 +85,7 @@ do | |||
| 85 | 打印 \大写! | 85 | 打印 \大写! |
| 86 | 86 | ||
| 87 | do | 87 | do |
| 88 | with 变量k.变量j = "乔" | 88 | with 变量k.变量j := "乔" |
| 89 | 打印 \大写! | 89 | 打印 \大写! |
| 90 | 90 | ||
| 91 | do | 91 | do |
| @@ -96,7 +96,7 @@ do | |||
| 96 | 96 | ||
| 97 | do | 97 | do |
| 98 | with 变量a | 98 | with 变量a |
| 99 | with .b = 2 | 99 | with .b := 2 |
| 100 | 打印 .c | 100 | 打印 .c |
| 101 | 101 | ||
| 102 | do | 102 | do |
| @@ -131,12 +131,12 @@ do | |||
| 131 | 131 | ||
| 132 | do | 132 | do |
| 133 | global 掩码 | 133 | global 掩码 |
| 134 | with? 掩码 = 实心矩形 宽: w, 高: h, 颜色: 0x66000000 | 134 | with? 掩码 := 实心矩形 宽: w, 高: h, 颜色: 0x66000000 |
| 135 | .触摸启用 = true | 135 | .触摸启用 = true |
| 136 | .吞噬触摸 = true | 136 | .吞噬触摸 = true |
| 137 | 137 | ||
| 138 | do | 138 | do |
| 139 | with? 掩码 = 实心矩形 宽: w, 高: h, 颜色: 0x66000000 | 139 | with? 掩码 := 实心矩形 宽: w, 高: h, 颜色: 0x66000000 |
| 140 | .触摸启用 = true | 140 | .触摸启用 = true |
| 141 | .吞噬触摸 = true | 141 | .吞噬触摸 = true |
| 142 | 142 | ||
diff --git a/spec/inputs/with.yue b/spec/inputs/with.yue index dcd4053..c1cf3e3 100644 --- a/spec/inputs/with.yue +++ b/spec/inputs/with.yue | |||
| @@ -48,21 +48,21 @@ do | |||
| 48 | with a -- only one value allowed | 48 | with a -- only one value allowed |
| 49 | print .world | 49 | print .world |
| 50 | 50 | ||
| 51 | mod = with _M = {} | 51 | mod = with _M := {} |
| 52 | .Thing = "hi" | 52 | .Thing = "hi" |
| 53 | 53 | ||
| 54 | -- operate on a only | 54 | -- operate on a only |
| 55 | with a, b = something, pooh | 55 | with a, b := something, pooh |
| 56 | print .world | 56 | print .world |
| 57 | 57 | ||
| 58 | x = with a, b = 1, 2 | 58 | x = with a, b := 1, 2 |
| 59 | print a + b | 59 | print a + b |
| 60 | 60 | ||
| 61 | print with a, b = 1, 2 | 61 | print with a, b := 1, 2 |
| 62 | print a + b | 62 | print a + b |
| 63 | 63 | ||
| 64 | -- assignment lhs must be evaluated in the order they appear | 64 | -- assignment lhs must be evaluated in the order they appear |
| 65 | p = with hello!.x, world!.y = 1, 2 | 65 | p = with hello!.x, world!.y := 1, 2 |
| 66 | print a + b | 66 | print a + b |
| 67 | 67 | ||
| 68 | -- | 68 | -- |
| @@ -73,16 +73,16 @@ do | |||
| 73 | x\upper! | 73 | x\upper! |
| 74 | 74 | ||
| 75 | do | 75 | do |
| 76 | with k = "jo" | 76 | with k := "jo" |
| 77 | print \upper! | 77 | print \upper! |
| 78 | 78 | ||
| 79 | do | 79 | do |
| 80 | with a,b,c = "", "", "" | 80 | with a,b,c := "", "", "" |
| 81 | print \upper! | 81 | print \upper! |
| 82 | 82 | ||
| 83 | do | 83 | do |
| 84 | a = "bunk" | 84 | a = "bunk" |
| 85 | with a,b,c = "", "", "" | 85 | with a,b,c := "", "", "" |
| 86 | print \upper! | 86 | print \upper! |
| 87 | 87 | ||
| 88 | do | 88 | do |
| @@ -90,7 +90,7 @@ do | |||
| 90 | print \upper! | 90 | print \upper! |
| 91 | 91 | ||
| 92 | do | 92 | do |
| 93 | with k.j = "jo" | 93 | with k.j := "jo" |
| 94 | print \upper! | 94 | print \upper! |
| 95 | 95 | ||
| 96 | do | 96 | do |
| @@ -103,7 +103,7 @@ do | |||
| 103 | do | 103 | do |
| 104 | with a | 104 | with a |
| 105 | -- nested `with`s with assignments should change the scope correctly | 105 | -- nested `with`s with assignments should change the scope correctly |
| 106 | with .b = 2 | 106 | with .b := 2 |
| 107 | print .c | 107 | print .c |
| 108 | 108 | ||
| 109 | do | 109 | do |
| @@ -138,12 +138,12 @@ do | |||
| 138 | 138 | ||
| 139 | do | 139 | do |
| 140 | global mask | 140 | global mask |
| 141 | with? mask = SolidRect width: w, height: h, color: 0x66000000 | 141 | with? mask := SolidRect width: w, height: h, color: 0x66000000 |
| 142 | .touchEnabled = true | 142 | .touchEnabled = true |
| 143 | .swallowTouches = true | 143 | .swallowTouches = true |
| 144 | 144 | ||
| 145 | do | 145 | do |
| 146 | with? mask = SolidRect width: w, height: h, color: 0x66000000 | 146 | with? mask := SolidRect width: w, height: h, color: 0x66000000 |
| 147 | .touchEnabled = true | 147 | .touchEnabled = true |
| 148 | .swallowTouches = true | 148 | .swallowTouches = true |
| 149 | 149 | ||
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua index c7a2d50..d857dec 100644 --- a/spec/outputs/codes_from_doc.lua +++ b/spec/outputs/codes_from_doc.lua | |||
| @@ -1234,7 +1234,7 @@ if "Robert" == name then | |||
| 1234 | elseif "Dan" == name or "Daniel" == name then | 1234 | elseif "Dan" == name or "Daniel" == name then |
| 1235 | print("Your name, it's Dan") | 1235 | print("Your name, it's Dan") |
| 1236 | else | 1236 | else |
| 1237 | print("I don't know about your name") | 1237 | print("I don't know about you with name " .. tostring(name)) |
| 1238 | end | 1238 | end |
| 1239 | local b = 1 | 1239 | local b = 1 |
| 1240 | local next_number | 1240 | local next_number |
| @@ -3450,7 +3450,7 @@ if "Robert" == name then | |||
| 3450 | elseif "Dan" == name or "Daniel" == name then | 3450 | elseif "Dan" == name or "Daniel" == name then |
| 3451 | print("Your name, it's Dan") | 3451 | print("Your name, it's Dan") |
| 3452 | else | 3452 | else |
| 3453 | print("I don't know about your name") | 3453 | print("I don't know about you with name " .. tostring(name)) |
| 3454 | end | 3454 | end |
| 3455 | local b = 1 | 3455 | local b = 1 |
| 3456 | local next_number | 3456 | local next_number |
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index fcde41f..ecab077 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua | |||
| @@ -1228,7 +1228,7 @@ if "Robert" == name then | |||
| 1228 | elseif "Dan" == name or "Daniel" == name then | 1228 | elseif "Dan" == name or "Daniel" == name then |
| 1229 | print("你的名字是Dan") | 1229 | print("你的名字是Dan") |
| 1230 | else | 1230 | else |
| 1231 | print("我不知道你的名字") | 1231 | print("我不认识你,你的名字是" .. tostring(name)) |
| 1232 | end | 1232 | end |
| 1233 | local b = 1 | 1233 | local b = 1 |
| 1234 | local next_number | 1234 | local next_number |
| @@ -3438,7 +3438,7 @@ if "Robert" == name then | |||
| 3438 | elseif "Dan" == name or "Daniel" == name then | 3438 | elseif "Dan" == name or "Daniel" == name then |
| 3439 | print("你的名字是Dan") | 3439 | print("你的名字是Dan") |
| 3440 | else | 3440 | else |
| 3441 | print("我不知道你的名字") | 3441 | print("我不认识你,你的名字是" .. tostring(name)) |
| 3442 | end | 3442 | end |
| 3443 | local b = 1 | 3443 | local b = 1 |
| 3444 | local next_number | 3444 | local next_number |
diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua index 0f8bba2..204b816 100644 --- a/spec/outputs/switch.lua +++ b/spec/outputs/switch.lua | |||
| @@ -656,4 +656,75 @@ do | |||
| 656 | end | 656 | end |
| 657 | end | 657 | end |
| 658 | end | 658 | end |
| 659 | do | ||
| 660 | local v = "hello" | ||
| 661 | if "hello" == v then | ||
| 662 | print("matched hello") | ||
| 663 | else | ||
| 664 | print("not matched") | ||
| 665 | end | ||
| 666 | end | ||
| 667 | do | ||
| 668 | local f | ||
| 669 | f = function() | ||
| 670 | return "ok" | ||
| 671 | end | ||
| 672 | local val = f() | ||
| 673 | if "ok" == val then | ||
| 674 | print("it's ok") | ||
| 675 | end | ||
| 676 | end | ||
| 677 | do | ||
| 678 | local g | ||
| 679 | g = function() | ||
| 680 | return 42 | ||
| 681 | end | ||
| 682 | local result = g() | ||
| 683 | if 1 == result or 2 == result then | ||
| 684 | print("small") | ||
| 685 | elseif 42 == result then | ||
| 686 | print("life universe everything") | ||
| 687 | else | ||
| 688 | print("other " .. tostring(result)) | ||
| 689 | end | ||
| 690 | end | ||
| 691 | do | ||
| 692 | local check | ||
| 693 | check = function() | ||
| 694 | if true then | ||
| 695 | return "yes" | ||
| 696 | else | ||
| 697 | return "no" | ||
| 698 | end | ||
| 699 | end | ||
| 700 | local x = check() | ||
| 701 | if "yes" == x then | ||
| 702 | print("affirmative") | ||
| 703 | else | ||
| 704 | print("negative") | ||
| 705 | end | ||
| 706 | end | ||
| 707 | do | ||
| 708 | local t | ||
| 709 | t = function() | ||
| 710 | local tb = { | ||
| 711 | a = 1 | ||
| 712 | } | ||
| 713 | tb.a = 2 | ||
| 714 | return tb | ||
| 715 | end | ||
| 716 | local data = t() | ||
| 717 | local _type_0 = type(data) | ||
| 718 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 719 | local _match_0 = false | ||
| 720 | if _tab_0 then | ||
| 721 | if 2 == data.a then | ||
| 722 | _match_0 = true | ||
| 723 | print("matched") | ||
| 724 | end | ||
| 725 | end | ||
| 726 | if not _match_0 then | ||
| 727 | print("not matched") | ||
| 728 | end | ||
| 729 | end | ||
| 659 | return nil | 730 | return nil |
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index fdb1d20..e69dd37 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
| @@ -372,8 +372,8 @@ std::string With_t::to_string(void* ud) const { | |||
| 372 | str_list temp{ | 372 | str_list temp{ |
| 373 | eop ? "with?"s : "with"s, | 373 | eop ? "with?"s : "with"s, |
| 374 | valueList->to_string(ud)}; | 374 | valueList->to_string(ud)}; |
| 375 | if (assigns) { | 375 | if (assign) { |
| 376 | temp.push_back(assigns->to_string(ud)); | 376 | temp.push_back(':' + assign->to_string(ud)); |
| 377 | } | 377 | } |
| 378 | if (body.is<Statement_t>()) { | 378 | if (body.is<Statement_t>()) { |
| 379 | return join(temp, " "sv) + " do "s + body->to_string(ud); | 379 | return join(temp, " "sv) + " do "s + body->to_string(ud); |
| @@ -419,6 +419,9 @@ std::string SwitchCase_t::to_string(void* ud) const { | |||
| 419 | std::string Switch_t::to_string(void* ud) const { | 419 | std::string Switch_t::to_string(void* ud) const { |
| 420 | auto info = reinterpret_cast<YueFormat*>(ud); | 420 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 421 | str_list temp{"switch "s + target->to_string(ud)}; | 421 | str_list temp{"switch "s + target->to_string(ud)}; |
| 422 | if (assignment) { | ||
| 423 | temp.back().append(" :"s + assignment->to_string(ud)); | ||
| 424 | } | ||
| 422 | info->pushScope(); | 425 | info->pushScope(); |
| 423 | for (auto branch : branches.objects()) { | 426 | for (auto branch : branches.objects()) { |
| 424 | temp.emplace_back(info->ind() + branch->to_string(ud)); | 427 | temp.emplace_back(info->ind() + branch->to_string(ud)); |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 0c15fac..946a587 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -287,9 +287,9 @@ AST_END(Return) | |||
| 287 | AST_NODE(With) | 287 | AST_NODE(With) |
| 288 | ast_ptr<false, ExistentialOp_t> eop; | 288 | ast_ptr<false, ExistentialOp_t> eop; |
| 289 | ast_ptr<true, ExpList_t> valueList; | 289 | ast_ptr<true, ExpList_t> valueList; |
| 290 | ast_ptr<false, Assign_t> assigns; | 290 | ast_ptr<false, Assign_t> assign; |
| 291 | ast_sel<true, Block_t, Statement_t> body; | 291 | ast_sel<true, Block_t, Statement_t> body; |
| 292 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) | 292 | AST_MEMBER(With, &eop, &valueList, &assign, &body) |
| 293 | AST_END(With) | 293 | AST_END(With) |
| 294 | 294 | ||
| 295 | AST_NODE(SwitchList) | 295 | AST_NODE(SwitchList) |
| @@ -304,20 +304,21 @@ AST_NODE(SwitchCase) | |||
| 304 | AST_MEMBER(SwitchCase, &condition, &body) | 304 | AST_MEMBER(SwitchCase, &condition, &body) |
| 305 | AST_END(SwitchCase) | 305 | AST_END(SwitchCase) |
| 306 | 306 | ||
| 307 | AST_NODE(Assignment) | ||
| 308 | ast_ptr<false, ExpList_t> expList; | ||
| 309 | ast_ptr<true, Assign_t> assign; | ||
| 310 | AST_MEMBER(Assignment, &expList, &assign) | ||
| 311 | AST_END(Assignment) | ||
| 312 | |||
| 307 | AST_NODE(Switch) | 313 | AST_NODE(Switch) |
| 308 | ast_ptr<true, Exp_t> target; | 314 | ast_ptr<true, Exp_t> target; |
| 315 | ast_ptr<false, Assignment_t> assignment; | ||
| 309 | ast_ptr<true, Seperator_t> sep; | 316 | ast_ptr<true, Seperator_t> sep; |
| 310 | ast_list<true, SwitchCase_t> branches; | 317 | ast_list<true, SwitchCase_t> branches; |
| 311 | ast_sel<false, Block_t, Statement_t> lastBranch; | 318 | ast_sel<false, Block_t, Statement_t> lastBranch; |
| 312 | AST_MEMBER(Switch, &target, &sep, &branches, &lastBranch) | 319 | AST_MEMBER(Switch, &target, &assignment, &sep, &branches, &lastBranch) |
| 313 | AST_END(Switch) | 320 | AST_END(Switch) |
| 314 | 321 | ||
| 315 | AST_NODE(Assignment) | ||
| 316 | ast_ptr<false, ExpList_t> expList; | ||
| 317 | ast_ptr<true, Assign_t> assign; | ||
| 318 | AST_MEMBER(Assignment, &expList, &assign) | ||
| 319 | AST_END(Assignment) | ||
| 320 | |||
| 321 | AST_NODE(IfCond) | 322 | AST_NODE(IfCond) |
| 322 | ast_ptr<true, Exp_t> condition; | 323 | ast_ptr<true, Exp_t> condition; |
| 323 | ast_ptr<false, Assignment_t> assignment; | 324 | ast_ptr<false, Assignment_t> assignment; |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 7abc929..9d2037f 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 78 | "close"s // Lua 5.4 | 78 | "close"s // Lua 5.4 |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | const std::string_view version = "0.28.3"sv; | 81 | const std::string_view version = "0.28.4"sv; |
| 82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
| 83 | 83 | ||
| 84 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
| @@ -9370,11 +9370,11 @@ private: | |||
| 9370 | std::string withVar; | 9370 | std::string withVar; |
| 9371 | bool needScope = !currentScope().lastStatement && !returnValue; | 9371 | bool needScope = !currentScope().lastStatement && !returnValue; |
| 9372 | bool extraScope = false; | 9372 | bool extraScope = false; |
| 9373 | if (with->assigns) { | 9373 | if (with->assign) { |
| 9374 | auto vars = getAssignVars(with); | 9374 | auto vars = getAssignVars(with); |
| 9375 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { | 9375 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { |
| 9376 | if (with->assigns->values.objects().size() == 1) { | 9376 | if (with->assign->values.objects().size() == 1) { |
| 9377 | auto var = singleVariableFrom(with->assigns->values.objects().front(), AccessType::Read); | 9377 | auto var = singleVariableFrom(with->assign->values.objects().front(), AccessType::Read); |
| 9378 | if (!var.empty() && isLocal(var)) { | 9378 | if (!var.empty() && isLocal(var)) { |
| 9379 | withVar = var; | 9379 | withVar = var; |
| 9380 | } | 9380 | } |
| @@ -9384,7 +9384,7 @@ private: | |||
| 9384 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 9384 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 9385 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); | 9385 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); |
| 9386 | auto assign = x->new_ptr<Assign_t>(); | 9386 | auto assign = x->new_ptr<Assign_t>(); |
| 9387 | assign->values.push_back(with->assigns->values.objects().front()); | 9387 | assign->values.push_back(with->assign->values.objects().front()); |
| 9388 | assignment->action.set(assign); | 9388 | assignment->action.set(assign); |
| 9389 | if (needScope) { | 9389 | if (needScope) { |
| 9390 | extraScope = true; | 9390 | extraScope = true; |
| @@ -9398,7 +9398,7 @@ private: | |||
| 9398 | auto assign = x->new_ptr<Assign_t>(); | 9398 | auto assign = x->new_ptr<Assign_t>(); |
| 9399 | assign->values.push_back(toAst<Exp_t>(withVar, x)); | 9399 | assign->values.push_back(toAst<Exp_t>(withVar, x)); |
| 9400 | bool skipFirst = true; | 9400 | bool skipFirst = true; |
| 9401 | for (auto value : with->assigns->values.objects()) { | 9401 | for (auto value : with->assign->values.objects()) { |
| 9402 | if (skipFirst) { | 9402 | if (skipFirst) { |
| 9403 | skipFirst = false; | 9403 | skipFirst = false; |
| 9404 | continue; | 9404 | continue; |
| @@ -9411,7 +9411,7 @@ private: | |||
| 9411 | withVar = vars.front(); | 9411 | withVar = vars.front(); |
| 9412 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 9412 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 9413 | assignment->expList.set(with->valueList); | 9413 | assignment->expList.set(with->valueList); |
| 9414 | assignment->action.set(with->assigns); | 9414 | assignment->action.set(with->assign); |
| 9415 | if (needScope) { | 9415 | if (needScope) { |
| 9416 | extraScope = true; | 9416 | extraScope = true; |
| 9417 | temp.push_back(indent() + "do"s + nll(with)); | 9417 | temp.push_back(indent() + "do"s + nll(with)); |
| @@ -10760,10 +10760,26 @@ private: | |||
| 10760 | pushScope(); | 10760 | pushScope(); |
| 10761 | } | 10761 | } |
| 10762 | bool extraScope = false; | 10762 | bool extraScope = false; |
| 10763 | if (switchNode->assignment) { | ||
| 10764 | if (needScope) { | ||
| 10765 | extraScope = true; | ||
| 10766 | temp.push_back(indent() + "do"s + nll(x)); | ||
| 10767 | pushScope(); | ||
| 10768 | } | ||
| 10769 | auto asmt = x->new_ptr<ExpListAssign_t>(); | ||
| 10770 | auto expList = x->new_ptr<ExpList_t>(); | ||
| 10771 | expList->exprs.push_back(switchNode->target); | ||
| 10772 | if (switchNode->assignment->expList) { | ||
| 10773 | expList->exprs.dup(switchNode->assignment->expList->exprs); | ||
| 10774 | } | ||
| 10775 | asmt->expList.set(expList); | ||
| 10776 | asmt->action.set(switchNode->assignment->assign); | ||
| 10777 | transformAssignment(asmt, temp); | ||
| 10778 | } | ||
| 10763 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); | 10779 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); |
| 10764 | if (objVar.empty() || !isLocal(objVar)) { | 10780 | if (objVar.empty() || !isLocal(objVar)) { |
| 10765 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { | 10781 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { |
| 10766 | if (needScope) { | 10782 | if (needScope && !extraScope) { |
| 10767 | extraScope = true; | 10783 | extraScope = true; |
| 10768 | temp.push_back(indent() + "do"s + nll(x)); | 10784 | temp.push_back(indent() + "do"s + nll(x)); |
| 10769 | pushScope(); | 10785 | pushScope(); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 078509c..0271e07 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -118,8 +118,8 @@ YueParser::YueParser() { | |||
| 118 | return false; | 118 | return false; |
| 119 | }); | 119 | }); |
| 120 | 120 | ||
| 121 | if_assignment_syntax_error = pl::user(true_(), [](const item_t& item) { | 121 | assignment_expression_syntax_error = pl::user(true_(), [](const item_t& item) { |
| 122 | throw ParserError("use := for if-assignment expression"sv, item.begin); | 122 | throw ParserError("use := for assignment expression"sv, item.begin); |
| 123 | return false; | 123 | return false; |
| 124 | }); | 124 | }); |
| 125 | 125 | ||
| @@ -356,7 +356,7 @@ YueParser::YueParser() { | |||
| 356 | 356 | ||
| 357 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); | 357 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); |
| 358 | 358 | ||
| 359 | with_exp = ExpList >> -(space >> Assign); | 359 | with_exp = ExpList >> -(space >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error)); |
| 360 | 360 | ||
| 361 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); | 361 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); |
| 362 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); | 362 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); |
| @@ -372,7 +372,8 @@ YueParser::YueParser() { | |||
| 372 | and_(SimpleTable | TableLit) >> Exp | | 372 | and_(SimpleTable | TableLit) >> Exp | |
| 373 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) | 373 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) |
| 374 | ); | 374 | ); |
| 375 | Switch = key("switch") >> space >> Exp >> | 375 | Switch = key("switch") >> space >> |
| 376 | Exp >> -(space >> Assignment) >> | ||
| 376 | space >> Seperator >> ( | 377 | space >> Seperator >> ( |
| 377 | SwitchCase >> space >> ( | 378 | SwitchCase >> space >> ( |
| 378 | switch_block | | 379 | switch_block | |
| @@ -381,7 +382,7 @@ YueParser::YueParser() { | |||
| 381 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent | 382 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent |
| 382 | ); | 383 | ); |
| 383 | 384 | ||
| 384 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error); | 385 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error); |
| 385 | IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))); | 386 | IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))); |
| 386 | if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); | 387 | if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); |
| 387 | if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; | 388 | if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 4488685..6263857 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -156,7 +156,7 @@ private: | |||
| 156 | NONE_AST_RULE(invalid_interpolation_error); | 156 | NONE_AST_RULE(invalid_interpolation_error); |
| 157 | NONE_AST_RULE(confusing_unary_not_error); | 157 | NONE_AST_RULE(confusing_unary_not_error); |
| 158 | NONE_AST_RULE(table_key_pair_error); | 158 | NONE_AST_RULE(table_key_pair_error); |
| 159 | NONE_AST_RULE(if_assignment_syntax_error); | 159 | NONE_AST_RULE(assignment_expression_syntax_error); |
| 160 | 160 | ||
| 161 | NONE_AST_RULE(inc_exp_level); | 161 | NONE_AST_RULE(inc_exp_level); |
| 162 | NONE_AST_RULE(dec_exp_level); | 162 | NONE_AST_RULE(dec_exp_level); |
