aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-09-08 09:26:49 +0800
committerLi Jin <dragon-fly@qq.com>2022-09-08 09:26:49 +0800
commitd4af1fa275b1d27229fc995f4a45137380040933 (patch)
tree955c76511d7021e6d1a0f06b46de3852eeac4176
parentdf85ad2e7f975026ca1e6bd84b26fff81c8d99c8 (diff)
downloadyuescript-d4af1fa275b1d27229fc995f4a45137380040933.tar.gz
yuescript-d4af1fa275b1d27229fc995f4a45137380040933.tar.bz2
yuescript-d4af1fa275b1d27229fc995f4a45137380040933.zip
redesigned metatable syntax. add support for destructuring a field with string and expression
-rwxr-xr-xdoc/docs/doc/README.md53
-rw-r--r--spec/inputs/assign.yue4
-rw-r--r--spec/inputs/class.yue6
-rw-r--r--spec/inputs/destructure.yue31
-rw-r--r--spec/inputs/existential.yue4
-rw-r--r--spec/inputs/import.yue6
-rw-r--r--spec/inputs/macro.yue2
-rw-r--r--spec/inputs/metatable.yue92
-rw-r--r--spec/inputs/switch.yue4
-rw-r--r--spec/outputs/destructure.lua61
-rw-r--r--spec/outputs/metatable.lua33
-rwxr-xr-xsrc/yuescript/yue_ast.h17
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp556
-rwxr-xr-xsrc/yuescript/yue_parser.cpp32
-rwxr-xr-xsrc/yuescript/yue_parser.h1
15 files changed, 605 insertions, 297 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
index 5f00860..5e81d4c 100755
--- a/doc/docs/doc/README.md
+++ b/doc/docs/doc/README.md
@@ -37,8 +37,8 @@ inventory =
37-- metatable manipulation 37-- metatable manipulation
38apple = 38apple =
39 size: 15 39 size: 15
40 index#: {color: 0x00ffff} 40 <index>: {color: 0x00ffff}
41p apple.color, apple.index# if apple.#? 41p apple.color, apple.<index> if apple.<>?
42 42
43-- js-like export syntax 43-- js-like export syntax
44export yuescript = "月之脚本" 44export yuescript = "月之脚本"
@@ -69,8 +69,8 @@ inventory =
69-- metatable manipulation 69-- metatable manipulation
70apple = 70apple =
71 size: 15 71 size: 15
72 index#: {color: 0x00ffff} 72 <index>: {color: 0x00ffff}
73p apple.color, apple.index# if apple.#? 73p apple.color, apple.<index> if apple.<>?
74 74
75-- js-like export syntax 75-- js-like export syntax
76export yuescript = "月之脚本" 76export yuescript = "月之脚本"
@@ -429,77 +429,78 @@ merge = {...a, ...b}
429 429
430### Metatable 430### Metatable
431 431
432The **#** operator can be used as a shortcut for metatable manipulation. 432The **<>** operator can be used as a shortcut for metatable manipulation.
433 433
434* **Metatable Creation** 434* **Metatable Creation**
435Create normal table with key **#** or metamethod key that ends with **#**. 435Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**.
436 436
437```moonscript 437```moonscript
438mt = {} 438mt = {}
439add = (right)=> #: mt, value: @value + right.value 439add = (right)=> <>: mt, value: @value + right.value
440mt.__add = add 440mt.__add = add
441 441
442a = #: mt, value: 1 442a = <>: mt, value: 1
443 -- set field with variable of the same name 443 -- set field with variable of the same name
444b = :add#, value: 2 444b = :<add>, value: 2
445c = add#: mt.__add, value: 3 445c = <add>: mt.__add, value: 3
446 446
447d = a + b + c 447d = a + b + c
448print d.value 448print d.value
449 449
450close _ = close#: -> print "out of scope" 450close _ = <close>: -> print "out of scope"
451``` 451```
452<YueDisplay> 452<YueDisplay>
453<pre> 453<pre>
454mt = {} 454mt = {}
455add = (right)=> #: mt, value: @value + right.value 455add = (right)=> <>: mt, value: @value + right.value
456mt.__add = add 456mt.__add = add
457 457
458a = #: mt, value: 1 458a = <>: mt, value: 1
459 -- set field with variable of the same name 459 -- set field with variable of the same name
460b = :add#, value: 2 460b = :<add>, value: 2
461c = add#: mt.__add, value: 3 461c = <add>: mt.__add, value: 3
462 462
463d = a + b + c 463d = a + b + c
464print d.value 464print d.value
465 465
466close _ = close#: -> print "out of scope" 466close _ = <close>: -> print "out of scope"
467</pre> 467</pre>
468</YueDisplay> 468</YueDisplay>
469 469
470* **Metatable Accessing** 470* **Metatable Accessing**
471Accessing metatable with key **#** or metamethod key that ends with **#**. 471Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**.
472 472
473```moonscript 473```moonscript
474-- create with metatable containing field "value" 474-- create with metatable containing field "value"
475tb = ["value"]#: 123 475tb = <"value">: 123
476tb.index# = tb.# 476tb.<index> = tb.<>
477print tb.value 477print tb.value
478 478
479tb.# = __index: {item: "hello"} 479tb.<> = __index: {item: "hello"}
480print tb.item 480print tb.item
481``` 481```
482<YueDisplay> 482<YueDisplay>
483
483<pre> 484<pre>
484-- create with metatable containing field "value" 485-- create with metatable containing field "value"
485tb = ["value"]#: 123 486tb = <"value">: 123
486tb.index# = tb.# 487tb.<index> = tb.<>
487print tb.value 488print tb.value
488tb.# = __index: {item: "hello"} 489tb.<> = __index: {item: "hello"}
489print tb.item 490print tb.item
490</pre> 491</pre>
491</YueDisplay> 492</YueDisplay>
492 493
493* **Metatable Destructure** 494* **Metatable Destructure**
494Destruct metatable with metamethod key that ends with **#**. 495Destruct metatable with metamethod key surrounded by **<>**.
495 496
496```moonscript 497```moonscript
497{item, :new, :close#, index#: getter} = tb 498{item, :new, :<close>, <index>: getter} = tb
498print item, new, close, getter 499print item, new, close, getter
499``` 500```
500<YueDisplay> 501<YueDisplay>
501<pre> 502<pre>
502{item, :new, :close#, index#: getter} = tb 503{item, :new, :<close>, <index>: getter} = tb
503print item, new, close, getter 504print item, new, close, getter
504</pre> 505</pre>
505</YueDisplay> 506</YueDisplay>
diff --git a/spec/inputs/assign.yue b/spec/inputs/assign.yue
index d04bcb8..da44dff 100644
--- a/spec/inputs/assign.yue
+++ b/spec/inputs/assign.yue
@@ -34,7 +34,7 @@ x = (do
34 34
35(using nil) <- _ 35(using nil) <- _
36 36
37a.# = do 37a.<> = do
38 print 123 38 print 123
39 {} 39 {}
40 40
@@ -63,7 +63,7 @@ do
63 123, tb 63 123, tb
64 64
65do 65do
66 a, b[], c, d.add# = if x 66 a, b[], c, d.<add> = if x
67 switch y 67 switch y
68 when 1 68 when 1
69 f! 69 f!
diff --git a/spec/inputs/class.yue b/spec/inputs/class.yue
index 9091d23..49537c2 100644
--- a/spec/inputs/class.yue
+++ b/spec/inputs/class.yue
@@ -237,9 +237,9 @@ class Example
237 237
238class Foo 238class Foo
239 new: (x) => @x = x 239 new: (x) => @x = x
240 mul#: (y) => @x * y 240 <mul>: (y) => @x * y
241 ["dsd-dsd"]#: 123 241 <"dsd-dsd">: 123
242 :add 242 :add
243 :add# 243 :<add>
244 244
245nil 245nil
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue
index 53f9ea3..ce593ec 100644
--- a/spec/inputs/destructure.yue
+++ b/spec/inputs/destructure.yue
@@ -160,17 +160,17 @@ do
160 160
161 {key1: {key2: value1 = 123}, :key3 = "abc"} = tb 161 {key1: {key2: value1 = 123}, :key3 = "abc"} = tb
162 162
163 {#: mt = {__index: {abc: 123}}, #: {:call# = (-> {}), :add#}} = tb 163 {<>: mt = {__index: {abc: 123}}, <>: {:<call> = (-> {}), :<add>}} = tb
164 164
165 {x: {#: mtx = {}}, :y, z: zItem, :index# = -> nil} = tb 165 {x: {<>: mtx = {}}, :y, z: zItem, :<index> = -> nil} = tb
166 166
167 {#: {func: a.b(-> 123).c = item?.defVal}} = tb 167 {<>: {func: a.b(-> 123).c = item?.defVal}} = tb
168 168
169do 169do
170 {#: mt = {}, sub#: subFunc} = tb.x 170 {<>: mt = {}, <sub>: subFunc} = tb.x
171 171
172do 172do
173 {x: {#: mt = {}, sub#: subFunc}} = tb 173 {x: {<>: mt = {}, <sub>: subFunc}} = tb
174 174
175do 175do
176 {a = 1, b = 2, c: {d.e = 3}} = tb 176 {a = 1, b = 2, c: {d.e = 3}} = tb
@@ -189,5 +189,24 @@ do
189 const {:x = 0.0, :y = 0.0} = point 189 const {:x = 0.0, :y = 0.0} = point
190 190
191do 191do
192 x1, x2, x3, a[], d, {b}, e, c.# = 1, 2, 3, f! 192 x1, x2, x3, a[], d, {b}, e, c.<> = 1, 2, 3, f!
193 y1, :y2, :y3, y4 = f1!, f2! 193 y1, :y2, :y3, y4 = f1!, f2!
194
195do
196 {
197 [["abc"]]: v1 = 111,
198 [1 + 1]: {v2 = 222, v3 = 333},
199 @x: v4 = 444
200 }, \
201 'x-y-z': v5, [func!]: {[func2!]: v6, v7} = tb, tb2
202
203do
204 <[name]>: value_meta, [name]: value = tb
205
206do
207 {:<tostring> = (-> "name"), :<add>} = tb
208
209 switch tb
210 when {:<name> = "item", <"123">: meta_field}
211 print name, meta_field
212
diff --git a/spec/inputs/existential.yue b/spec/inputs/existential.yue
index 101e1d8..e73b421 100644
--- a/spec/inputs/existential.yue
+++ b/spec/inputs/existential.yue
@@ -49,9 +49,9 @@ with? io.open "test.txt", "w"
49 \write "hello" 49 \write "hello"
50 \close! 50 \close!
51 51
52tb?.a#? 123 52tb?.<a>? 123
53 53
54with? tb.#?.index# 54with? tb.<>?.<index>
55 .a = 1 55 .a = 1
56 56
57nil 57nil
diff --git a/spec/inputs/import.yue b/spec/inputs/import.yue
index 570b909..af5545d 100644
--- a/spec/inputs/import.yue
+++ b/spec/inputs/import.yue
@@ -64,8 +64,8 @@ do
64 import "org.package.module" as function:func, if:ifVar 64 import "org.package.module" as function:func, if:ifVar
65 65
66do 66do
67 import "m" as {a#: b} 67 import "m" as {<a>: b}
68 import "m" as {e: f, a#: c} 68 import "m" as {e: f, <a>: c}
69 import "m" as {c: d} 69 import "m" as {c: d}
70 import "m" as {g, {h#: i}} 70 import "m" as {g, {<h>: i}}
71 71
diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue
index 3c89c1c..ac51d85 100644
--- a/spec/inputs/macro.yue
+++ b/spec/inputs/macro.yue
@@ -262,7 +262,7 @@ $chainC(
262 Destroy! 262 Destroy!
263) 263)
264 264
265macro tb = -> "{'abc', a:123, call#:=> 998}" 265macro tb = -> "{'abc', a:123, <call>:=> 998}"
266print $tb[1], $tb.a, ($tb)!, $tb! 266print $tb[1], $tb.a, ($tb)!, $tb!
267 267
268print "current line: #{ $LINE }" 268print "current line: #{ $LINE }"
diff --git a/spec/inputs/metatable.yue b/spec/inputs/metatable.yue
index 86991c2..61cc266 100644
--- a/spec/inputs/metatable.yue
+++ b/spec/inputs/metatable.yue
@@ -1,62 +1,86 @@
1a = close: true, close#: => print "out of scope" 1a = close: true, <close>: => print "out of scope"
2b = add#: (left, right)-> right - left 2b = <add>: (left, right)-> right - left
3c = key1: true, :add#, key2: true 3c = key1: true, :<add>, key2: true
4w = [name]#:123, ["new"]#:(val)=> {val} 4w = <[name]>:123, <"new">:(val)=> {val}
5w.#["new"] w.#[name] 5w.<>["new"] w.<>[name]
6 6
7do close _ = close#: -> print "out of scope" 7do close _ = <close>: -> print "out of scope"
8 8
9d, e = a.close, a.close# 9d, e = a.close, a.<close>
10 10
11f = a\close# 1 11f = a\<close> 1
12a.add# = (x, y)-> x + y 12a.<add> = (x, y)-> x + y
13 13
14do 14do
15 {:new, :close#, close#: closeA} = a 15 {:new, :<close>, <close>: closeA} = a
16 print new, close, closeA 16 print new, close, closeA
17 17
18do 18do
19 local * 19 local *
20 x, \ 20 x, \
21 {:new, :var, :close#, close#: closeA}, \ 21 {:new, :var, :<close>, <close>: closeA}, \
22 :num, :add#, :sub# \ 22 :num, :<add>, :<sub> \
23 = 123, a.b.c, func! 23 = 123, a.b.c, func!
24 24
25x.abc, a.b.# = 123, {} 25x.abc, a.b.<> = 123, {}
26func!.# = mt --, extra 26func!.<> = mt --, extra
27a, b.c.#, d, e = 1, mt, "abc", nil 27a, b.c.<>, d, e = 1, mt, "abc", nil
28 28
29is_same = a.#.__index == a.index# 29is_same = a.<>.__index == a.<index>
30 30
31-- 31--
32a.# = __index: tb 32a.<> = __index: tb
33a.#.__index = tb 33a.<>.__index = tb
34a.index# = tb 34a.<index> = tb
35-- 35--
36 36
37mt = a.# 37mt = a.<>
38 38
39tb\func #list 39tb\func #list
40tb\func#list 40tb\<func>list
41tb\func# list 41tb\<func> list
42 42
43import "module" as :index#, newindex#:setFunc 43import "module" as :<index>, <newindex>:setFunc
44 44
45with tb 45with tb
46 print .add#, .x\index# "key" 46 print .<add>, .x\<index> "key"
47 a = .index#.add#\new# 123 47 a = .<index>.<add>\<new> 123
48 b = t#.close#.test 48 b = t#.<close>.test
49 c = t #.close# .test 49 c = t #.<close> .test
50 50
51#:mt = a 51<>:mt = a
52a = #:mt 52a = <>:mt
53a = #:__index:mt 53a = <>:__index:mt
54 54
55local index 55local index
56#:__index:index = a 56<>:__index:index = a
57:index# = a 57:<index> = a
58 58
59do #:{new:ctor, :update} = a 59do <>:{new:ctor, :update} = a
60do {new:ctor, :update} = a.# 60do {new:ctor, :update} = a.<>
61
62tb = {}
63do
64 f = tb\<"value#{x < y}">(123, ...)
65 f tb\<'value'> 123, ...
66 tb\<[[
67 value
68 1
69 ]]>(123, ...)
70 return tb\<["value" .. tostring x > y]>(123, ...)
71
72do
73 f = tb\<value>(123, ...)
74 f tb\<value>(123, ...)
75 tb\<value>(123, ...)
76 return tb\<value> 123, ...
77
78do
79 f = tb.<value> 123, ...
80 f = tb.<"value#{x < y}">(123, ...)
81 f tb.<'value'> 123, ...
82 tb.<[[ value
831]]>(123, ...)
84 return tb.<["value" .. tostring x > y]>(123, ...)
61 85
62nil 86nil
diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue
index 442d15f..cb1eb31 100644
--- a/spec/inputs/switch.yue
+++ b/spec/inputs/switch.yue
@@ -101,7 +101,7 @@ do
101 print "Object A" 101 print "Object A"
102 when ClassB 102 when ClassB
103 print "Object B" 103 print "Object B"
104 when #: mt 104 when <>: mt
105 print "A table with metatable" 105 print "A table with metatable"
106 else 106 else
107 print "item not accepted!" 107 print "item not accepted!"
@@ -156,7 +156,7 @@ do
156 156
157do 157do
158 switch y 158 switch y
159 when {x: #: mt} 159 when {x: <>: mt}
160 print mt 160 print mt
161 161
162nil 162nil
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua
index dfac42c..0da920e 100644
--- a/spec/outputs/destructure.lua
+++ b/spec/outputs/destructure.lua
@@ -428,3 +428,64 @@ do
428 y2, y3 = _obj_0.y2, _obj_0.y3 428 y2, y3 = _obj_0.y2, _obj_0.y3
429 end 429 end
430end 430end
431do
432 local v1, v2, v3, v4
433 do
434 local _obj_0 = tb
435 local _tmp_0, _tmp_1 = 1 + 1, self.x
436 v1, v2, v3, v4 = _obj_0[ [["abc"]]], _obj_0[_tmp_0][1], _obj_0[_tmp_0][2], _obj_0[_tmp_1]
437 if v1 == nil then
438 v1 = 111
439 end
440 if v2 == nil then
441 v2 = 222
442 end
443 if v3 == nil then
444 v3 = 333
445 end
446 if v4 == nil then
447 v4 = 444
448 end
449 end
450 local v5, v6, v7
451 do
452 local _obj_0 = tb2
453 local _tmp_2, _tmp_3 = func(), func2()
454 v5, v6, v7 = _obj_0['x-y-z'], _obj_0[_tmp_2][_tmp_3], _obj_0[_tmp_2][1]
455 end
456end
457do
458 local _obj_0 = tb
459 local value = _obj_0[name]
460 local value_meta = getmetatable(_obj_0)[name]
461end
462do
463 local tostring, add
464 do
465 local _obj_0 = getmetatable(tb)
466 tostring, add = _obj_0.__tostring, _obj_0.__add
467 if tostring == nil then
468 tostring = (function()
469 return "name"
470 end)
471 end
472 end
473 local _exp_0 = tb
474 do
475 local _tab_0 = "table" == type(_exp_0)
476 if _tab_0 then
477 local name, meta_field
478 do
479 local _obj_0 = getmetatable(_exp_0)
480 name = _obj_0.__name
481 meta_field = _obj_0["123"]
482 if name == nil then
483 name = "item"
484 end
485 end
486 if meta_field ~= nil then
487 return print(name, meta_field)
488 end
489 end
490 end
491end
diff --git a/spec/outputs/metatable.lua b/spec/outputs/metatable.lua
index 6f5ceed..937136f 100644
--- a/spec/outputs/metatable.lua
+++ b/spec/outputs/metatable.lua
@@ -111,4 +111,37 @@ do
111 ctor, update = _obj_0.new, _obj_0.update 111 ctor, update = _obj_0.new, _obj_0.update
112 end 112 end
113end 113end
114local tb = { }
115do
116 do
117 local _obj_0 = getmetatable(tb)
118 f = _obj_0["value" .. tostring(x < y)](_obj_0, 123, ...)
119 end
120 f((function(...)
121 local _obj_0 = getmetatable(tb)
122 return _obj_0['value'](_obj_0, 123, ...)
123 end)(...))
124 do
125 local _obj_0 = getmetatable(tb)
126 _obj_0[ [[ value
127 1
128 ]]](_obj_0, 123, ...)
129 end
130 local _obj_0 = getmetatable(tb)
131 return _obj_0["value" .. tostring(x > y)](_obj_0, 123, ...)
132end
133do
134 f = getmetatable(tb):__value(123, ...)
135 f(getmetatable(tb):__value(123, ...))
136 getmetatable(tb):__value(123, ...)
137 return getmetatable(tb):__value(123, ...)
138end
139do
140 f = getmetatable(tb).__value(123, ...)
141 f = getmetatable(tb)["value" .. tostring(x < y)](123, ...)
142 f(getmetatable(tb)['value'](123, ...))
143 getmetatable(tb)[ [[ value
1441]]](123, ...)
145 return getmetatable(tb)["value" .. tostring(x > y)](123, ...)
146end
114return nil 147return nil
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 386fa28..d8f6c95 100755
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -459,18 +459,16 @@ AST_NODE(variable_pair)
459 AST_MEMBER(variable_pair, &name) 459 AST_MEMBER(variable_pair, &name)
460AST_END(variable_pair, "variable_pair"sv) 460AST_END(variable_pair, "variable_pair"sv)
461 461
462class DoubleString_t; 462class String_t;
463class SingleString_t;
464class LuaString_t;
465 463
466AST_NODE(normal_pair) 464AST_NODE(normal_pair)
467 ast_sel<true, KeyName_t, Exp_t, DoubleString_t, SingleString_t, LuaString_t> key; 465 ast_sel<true, KeyName_t, Exp_t, String_t> key;
468 ast_sel<true, Exp_t, TableBlock_t> value; 466 ast_sel<true, Exp_t, TableBlock_t> value;
469 AST_MEMBER(normal_pair, &key, &value) 467 AST_MEMBER(normal_pair, &key, &value)
470AST_END(normal_pair, "normal_pair"sv) 468AST_END(normal_pair, "normal_pair"sv)
471 469
472AST_NODE(default_pair) 470AST_NODE(default_pair)
473 ast_sel<true, Variable_t, KeyName_t, Exp_t> key; 471 ast_sel<true, Variable_t, KeyName_t, Exp_t, String_t> key;
474 ast_ptr<true, Seperator_t> sep; 472 ast_ptr<true, Seperator_t> sep;
475 ast_ptr<false, Exp_t> value; 473 ast_ptr<false, Exp_t> value;
476 ast_ptr<true, Exp_t> defVal; 474 ast_ptr<true, Exp_t> defVal;
@@ -483,13 +481,13 @@ AST_NODE(meta_variable_pair)
483AST_END(meta_variable_pair, "meta_variable_pair"sv) 481AST_END(meta_variable_pair, "meta_variable_pair"sv)
484 482
485AST_NODE(meta_normal_pair) 483AST_NODE(meta_normal_pair)
486 ast_sel<false, Name_t, Exp_t> key; 484 ast_sel<false, Name_t, Exp_t, String_t> key;
487 ast_sel<true, Exp_t, TableBlock_t> value; 485 ast_sel<true, Exp_t, TableBlock_t> value;
488 AST_MEMBER(meta_normal_pair, &key, &value) 486 AST_MEMBER(meta_normal_pair, &key, &value)
489AST_END(meta_normal_pair, "meta_normal_pair"sv) 487AST_END(meta_normal_pair, "meta_normal_pair"sv)
490 488
491AST_NODE(meta_default_pair) 489AST_NODE(meta_default_pair)
492 ast_sel<false, Variable_t, Name_t> key; 490 ast_sel<false, Variable_t, Name_t, Exp_t, String_t> key;
493 ast_ptr<true, Seperator_t> sep; 491 ast_ptr<true, Seperator_t> sep;
494 ast_ptr<false, Exp_t> value; 492 ast_ptr<false, Exp_t> value;
495 ast_ptr<true, Exp_t> defVal; 493 ast_ptr<true, Exp_t> defVal;
@@ -502,7 +500,6 @@ AST_NODE(simple_table)
502 AST_MEMBER(simple_table, &sep, &pairs) 500 AST_MEMBER(simple_table, &sep, &pairs)
503AST_END(simple_table, "simple_table"sv) 501AST_END(simple_table, "simple_table"sv)
504 502
505class String_t;
506class const_value_t; 503class const_value_t;
507class ClassDecl_t; 504class ClassDecl_t;
508class unary_value_t; 505class unary_value_t;
@@ -560,8 +557,8 @@ AST_LEAF(Metatable)
560AST_END(Metatable, "metatable"sv) 557AST_END(Metatable, "metatable"sv)
561 558
562AST_NODE(Metamethod) 559AST_NODE(Metamethod)
563 ast_ptr<true, Name_t> name; 560 ast_sel<true, Name_t, Exp_t, String_t> item;
564 AST_MEMBER(Metamethod, &name) 561 AST_MEMBER(Metamethod, &item)
565AST_END(Metamethod, "metamethod"sv) 562AST_END(Metamethod, "metamethod"sv)
566 563
567AST_NODE(DotChainItem) 564AST_NODE(DotChainItem)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 17979ab..73b4ae9 100755
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -59,7 +59,7 @@ namespace yue {
59 59
60typedef std::list<std::string> str_list; 60typedef std::list<std::string> str_list;
61 61
62const std::string_view version = "0.14.5"sv; 62const std::string_view version = "0.15.1"sv;
63const std::string_view extension = "yue"sv; 63const std::string_view extension = "yue"sv;
64 64
65class YueCompilerImpl { 65class YueCompilerImpl {
@@ -296,7 +296,7 @@ private:
296 struct DestructItem { 296 struct DestructItem {
297 ast_ptr<true, Exp_t> target; 297 ast_ptr<true, Exp_t> target;
298 std::string targetVar; 298 std::string targetVar;
299 std::string structure; 299 ast_ptr<false, ChainValue_t> structure;
300 ast_ptr<true, Exp_t> defVal; 300 ast_ptr<true, Exp_t> defVal;
301 }; 301 };
302 302
@@ -304,6 +304,7 @@ private:
304 ast_ptr<true, ast_node> value; 304 ast_ptr<true, ast_node> value;
305 std::string valueVar; 305 std::string valueVar;
306 std::list<DestructItem> items; 306 std::list<DestructItem> items;
307 ast_ptr<false, ExpListAssign_t> inlineAssignment;
307 }; 308 };
308 309
309 enum class ExpUsage { 310 enum class ExpUsage {
@@ -614,6 +615,24 @@ private:
614 return nullptr; 615 return nullptr;
615 } 616 }
616 617
618 ast_ptr<false, Exp_t> newExp(SimpleValue_t* simpleValue, ast_node* x) {
619 auto value = x->new_ptr<Value_t>();
620 value->item.set(simpleValue);
621 return newExp(value, x);
622 }
623
624 ast_ptr<false, Exp_t> newExp(String_t* string, ast_node* x) {
625 auto value = x->new_ptr<Value_t>();
626 value->item.set(string);
627 return newExp(value, x);
628 }
629
630 ast_ptr<false, Exp_t> newExp(ChainValue_t* chainValue, ast_node* x) {
631 auto value = x->new_ptr<Value_t>();
632 value->item.set(chainValue);
633 return newExp(value, x);
634 }
635
617 ast_ptr<false, Exp_t> newExp(Value_t* value, ast_node* x) { 636 ast_ptr<false, Exp_t> newExp(Value_t* value, ast_node* x) {
618 auto unary = x->new_ptr<unary_exp_t>(); 637 auto unary = x->new_ptr<unary_exp_t>();
619 unary->expos.push_back(value); 638 unary->expos.push_back(value);
@@ -772,7 +791,8 @@ private:
772 HasEOP, 791 HasEOP,
773 HasKeyword, 792 HasKeyword,
774 Macro, 793 Macro,
775 Metatable 794 Metatable,
795 MetaFieldInvocation
776 }; 796 };
777 797
778 ChainType specialChainValue(ChainValue_t* chainValue) const { 798 ChainType specialChainValue(ChainValue_t* chainValue) const {
@@ -795,6 +815,8 @@ private:
795 if (auto colonChain = ast_cast<ColonChainItem_t>(item)) { 815 if (auto colonChain = ast_cast<ColonChainItem_t>(item)) {
796 if (ast_is<LuaKeyword_t>(colonChain->name)) { 816 if (ast_is<LuaKeyword_t>(colonChain->name)) {
797 type = ChainType::HasKeyword; 817 type = ChainType::HasKeyword;
818 } else if (auto meta = colonChain->name.as<Metamethod_t>(); meta && !meta->item.is<Name_t>()) {
819 return ChainType::MetaFieldInvocation;
798 } 820 }
799 } else if (ast_is<existential_op_t>(item)) { 821 } else if (ast_is<existential_op_t>(item)) {
800 return ChainType::HasEOP; 822 return ChainType::HasEOP;
@@ -1013,9 +1035,7 @@ private:
1013 case id<With_t>(): { 1035 case id<With_t>(): {
1014 auto simpleValue = x->new_ptr<SimpleValue_t>(); 1036 auto simpleValue = x->new_ptr<SimpleValue_t>();
1015 simpleValue->value.set(val); 1037 simpleValue->value.set(val);
1016 auto value = x->new_ptr<Value_t>(); 1038 auto exp = newExp(simpleValue, x);
1017 value->item.set(simpleValue);
1018 auto exp = newExp(value, x);
1019 expList->exprs.push_back(exp); 1039 expList->exprs.push_back(exp);
1020 break; 1040 break;
1021 } 1041 }
@@ -1025,9 +1045,7 @@ private:
1025 tabLit->values.dup(tableBlock->values); 1045 tabLit->values.dup(tableBlock->values);
1026 auto simpleValue = x->new_ptr<SimpleValue_t>(); 1046 auto simpleValue = x->new_ptr<SimpleValue_t>();
1027 simpleValue->value.set(tabLit); 1047 simpleValue->value.set(tabLit);
1028 auto value = x->new_ptr<Value_t>(); 1048 auto exp = newExp(simpleValue, x);
1029 value->item.set(simpleValue);
1030 auto exp = newExp(value, x);
1031 expList->exprs.push_back(exp); 1049 expList->exprs.push_back(exp);
1032 break; 1050 break;
1033 } 1051 }
@@ -1072,9 +1090,7 @@ private:
1072 statement->appendix.set(nullptr); 1090 statement->appendix.set(nullptr);
1073 auto simpleValue = x->new_ptr<SimpleValue_t>(); 1091 auto simpleValue = x->new_ptr<SimpleValue_t>();
1074 simpleValue->value.set(ifNode); 1092 simpleValue->value.set(ifNode);
1075 auto value = x->new_ptr<Value_t>(); 1093 auto exp = newExp(simpleValue, x);
1076 value->item.set(simpleValue);
1077 auto exp = newExp(value, x);
1078 auto expList = x->new_ptr<ExpList_t>(); 1094 auto expList = x->new_ptr<ExpList_t>();
1079 expList->exprs.push_back(exp); 1095 expList->exprs.push_back(exp);
1080 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 1096 auto expListAssign = x->new_ptr<ExpListAssign_t>();
@@ -1091,9 +1107,7 @@ private:
1091 comp->value.set(stmt); 1107 comp->value.set(stmt);
1092 auto simpleValue = x->new_ptr<SimpleValue_t>(); 1108 auto simpleValue = x->new_ptr<SimpleValue_t>();
1093 simpleValue->value.set(comp); 1109 simpleValue->value.set(comp);
1094 auto value = x->new_ptr<Value_t>(); 1110 auto exp = newExp(simpleValue, x);
1095 value->item.set(simpleValue);
1096 auto exp = newExp(value, x);
1097 auto expList = x->new_ptr<ExpList_t>(); 1111 auto expList = x->new_ptr<ExpList_t>();
1098 expList->exprs.push_back(exp); 1112 expList->exprs.push_back(exp);
1099 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 1113 auto expListAssign = x->new_ptr<ExpListAssign_t>();
@@ -1483,9 +1497,7 @@ private:
1483 args.push_back(_withVars.top()); 1497 args.push_back(_withVars.top());
1484 } 1498 }
1485 } else { 1499 } else {
1486 auto value = tmpChain->new_ptr<Value_t>(); 1500 transformExp(newExp(tmpChain, tmpChain), args, ExpUsage::Closure);
1487 value->item.set(tmpChain);
1488 transformExp(newExp(value, tmpChain), args, ExpUsage::Closure);
1489 } 1501 }
1490 if (vit == values.end()) { 1502 if (vit == values.end()) {
1491 throw std::logic_error(_info.errorMessage("right value missing"sv, values.front())); 1503 throw std::logic_error(_info.errorMessage("right value missing"sv, values.front()));
@@ -1514,9 +1526,7 @@ private:
1514 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1526 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1515 newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); 1527 newAssignment->expList.set(toAst<ExpList_t>(objVar, x));
1516 auto assign = x->new_ptr<Assign_t>(); 1528 auto assign = x->new_ptr<Assign_t>();
1517 auto value = tmpChain->new_ptr<Value_t>(); 1529 assign->values.push_back(newExp(tmpChain, tmpChain));
1518 value->item.set(tmpChain);
1519 assign->values.push_back(newExp(value, tmpChain));
1520 newAssignment->action.set(assign); 1530 newAssignment->action.set(assign);
1521 transformAssignment(newAssignment, temp); 1531 transformAssignment(newAssignment, temp);
1522 varName = objVar; 1532 varName = objVar;
@@ -1685,7 +1695,8 @@ private:
1685 auto expList = assignment->expList.get(); 1695 auto expList = assignment->expList.get();
1686 switch (type) { 1696 switch (type) {
1687 case ChainType::HasEOP: 1697 case ChainType::HasEOP:
1688 case ChainType::EndWithColon: { 1698 case ChainType::EndWithColon:
1699 case ChainType::MetaFieldInvocation: {
1689 std::string preDefine = getPreDefineLine(assignment); 1700 std::string preDefine = getPreDefineLine(assignment);
1690 transformChainValue(chainValue, out, ExpUsage::Assignment, expList); 1701 transformChainValue(chainValue, out, ExpUsage::Assignment, expList);
1691 out.back().insert(0, preDefine); 1702 out.back().insert(0, preDefine);
@@ -1714,7 +1725,7 @@ private:
1714 for (auto& destruct : info.destructures) { 1725 for (auto& destruct : info.destructures) {
1715 std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; 1726 std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs;
1716 bool extraScope = false; 1727 bool extraScope = false;
1717 if (destruct.items.size() == 1) { 1728 if (!destruct.inlineAssignment && destruct.items.size() == 1) {
1718 auto& pair = destruct.items.front(); 1729 auto& pair = destruct.items.front();
1719 if (pair.targetVar.empty() && pair.defVal) { 1730 if (pair.targetVar.empty() && pair.defVal) {
1720 extraScope = true; 1731 extraScope = true;
@@ -1725,21 +1736,13 @@ private:
1725 pair.targetVar = objVar; 1736 pair.targetVar = objVar;
1726 } else if (auto val = singleValueFrom(destruct.value); val->item.is<ChainValue_t>()) { 1737 } else if (auto val = singleValueFrom(destruct.value); val->item.is<ChainValue_t>()) {
1727 auto chainValue = static_cast<ChainValue_t*>(val->item.get()); 1738 auto chainValue = static_cast<ChainValue_t*>(val->item.get());
1728 int added = 0; 1739 auto newChain = val->item->new_ptr<ChainValue_t>();
1729 if (!pair.structure.empty()) { 1740 newChain->items.dup(chainValue->items);
1730 auto appendChain = toAst<ChainValue_t>("x"s + pair.structure, x); 1741 if (pair.structure) {
1731 appendChain->items.pop_front(); 1742 newChain->items.dup(pair.structure->items);
1732 for (auto item : appendChain->items.objects()) {
1733 chainValue->items.push_back(item);
1734 added++;
1735 }
1736 } 1743 }
1737 auto newAssignment = assignmentFrom(pair.target, destruct.value, x); 1744 auto newAssignment = assignmentFrom(pair.target, newExp(newChain, val->item), x);
1738 transformAssignment(newAssignment, temp); 1745 transformAssignment(newAssignment, temp);
1739 while (added > 0) {
1740 chainValue->items.pop_back();
1741 added--;
1742 }
1743 if (pair.defVal) { 1746 if (pair.defVal) {
1744 bool isNil = false; 1747 bool isNil = false;
1745 if (auto v1 = singleValueFrom(pair.defVal)) { 1748 if (auto v1 = singleValueFrom(pair.defVal)) {
@@ -1782,7 +1785,10 @@ private:
1782 auto newAssignment = assignmentFrom(toAst<Exp_t>(objVar, x), destruct.value, x); 1785 auto newAssignment = assignmentFrom(toAst<Exp_t>(objVar, x), destruct.value, x);
1783 transformAssignment(newAssignment, temp); 1786 transformAssignment(newAssignment, temp);
1784 } 1787 }
1785 auto valueExp = toAst<Exp_t>(objVar + pair.structure, x); 1788 auto chain = pair.target->new_ptr<ChainValue_t>();
1789 chain->items.push_back(toAst<Callable_t>(objVar, chain));
1790 chain->items.dup(pair.structure->items);
1791 auto valueExp = newExp(chain, pair.target);
1786 auto newAssignment = assignmentFrom(pair.target, valueExp, x); 1792 auto newAssignment = assignmentFrom(pair.target, valueExp, x);
1787 transformAssignment(newAssignment, temp); 1793 transformAssignment(newAssignment, temp);
1788 if (!isLocalValue) { 1794 if (!isLocalValue) {
@@ -1791,7 +1797,8 @@ private:
1791 temp.push_back(clearBuf()); 1797 temp.push_back(clearBuf());
1792 } 1798 }
1793 } else { 1799 } else {
1794 str_list values, defs; 1800 str_list defs;
1801 std::list<ast_ptr<false, ChainValue_t>> values;
1795 std::list<Exp_t*> names; 1802 std::list<Exp_t*> names;
1796 pushScope(); 1803 pushScope();
1797 for (auto& item : destruct.items) { 1804 for (auto& item : destruct.items) {
@@ -1813,8 +1820,9 @@ private:
1813 } 1820 }
1814 popScope(); 1821 popScope();
1815 if (_parser.match<Name_t>(destruct.valueVar) && isLocal(destruct.valueVar)) { 1822 if (_parser.match<Name_t>(destruct.valueVar) && isLocal(destruct.valueVar)) {
1823 auto callable = toAst<Callable_t>(destruct.valueVar, destruct.value);
1816 for (auto& v : values) { 1824 for (auto& v : values) {
1817 v.insert(0, destruct.valueVar); 1825 v->items.push_front(callable);
1818 } 1826 }
1819 if (extraScope) { 1827 if (extraScope) {
1820 if (!defs.empty()) { 1828 if (!defs.empty()) {
@@ -1842,17 +1850,22 @@ private:
1842 auto targetVar = toAst<Exp_t>(valVar, destruct.value); 1850 auto targetVar = toAst<Exp_t>(valVar, destruct.value);
1843 auto newAssignment = assignmentFrom(targetVar, destruct.value, destruct.value); 1851 auto newAssignment = assignmentFrom(targetVar, destruct.value, destruct.value);
1844 transformAssignment(newAssignment, temp); 1852 transformAssignment(newAssignment, temp);
1853 auto callable = singleValueFrom(targetVar)->item.to<ChainValue_t>()->items.front();
1845 for (auto& v : values) { 1854 for (auto& v : values) {
1846 v.insert(0, valVar); 1855 v->items.push_front(callable);
1847 } 1856 }
1848 } 1857 }
1858 if (destruct.inlineAssignment) {
1859 transformAssignment(destruct.inlineAssignment, temp);
1860 }
1849 if (optionalDestruct) { 1861 if (optionalDestruct) {
1850 while (!names.empty()) { 1862 while (!names.empty()) {
1851 auto name = names.front(); 1863 auto name = names.front();
1852 names.pop_front(); 1864 names.pop_front();
1853 auto value = values.front(); 1865 auto value = values.front().get();
1866 auto valueList = value->new_ptr<ExpList_t>();
1867 valueList->exprs.push_back(newExp(value, value));
1854 values.pop_front(); 1868 values.pop_front();
1855 auto valueList = toAst<ExpList_t>(value, x);
1856 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1869 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1857 auto assignList = x->new_ptr<ExpList_t>(); 1870 auto assignList = x->new_ptr<ExpList_t>();
1858 assignList->exprs.push_back(name); 1871 assignList->exprs.push_back(name);
@@ -1863,7 +1876,10 @@ private:
1863 transformAssignment(newAssignment, temp); 1876 transformAssignment(newAssignment, temp);
1864 } 1877 }
1865 } else { 1878 } else {
1866 auto valueList = toAst<ExpList_t>(join(values, ","sv), x); 1879 auto valueList = x->new_ptr<ExpList_t>();
1880 for (const auto& v : values) {
1881 valueList->exprs.push_back(newExp(v, v));
1882 }
1867 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1883 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1868 auto assignList = x->new_ptr<ExpList_t>(); 1884 auto assignList = x->new_ptr<ExpList_t>();
1869 for (auto name : names) { 1885 for (auto name : names) {
@@ -1923,7 +1939,7 @@ private:
1923 1939
1924 std::list<DestructItem> destructFromExp(ast_node* node, bool optional) { 1940 std::list<DestructItem> destructFromExp(ast_node* node, bool optional) {
1925 const node_container* tableItems = nullptr; 1941 const node_container* tableItems = nullptr;
1926 auto sep = optional ? "?"s : Empty; 1942 ast_ptr<false, existential_op_t> sep = optional ? node->new_ptr<existential_op_t>() : nullptr;
1927 switch (node->getId()) { 1943 switch (node->getId()) {
1928 case id<Exp_t>(): { 1944 case id<Exp_t>(): {
1929 auto item = singleValueFrom(node)->item.get(); 1945 auto item = singleValueFrom(node)->item.get();
@@ -1965,17 +1981,20 @@ private:
1965 if (ast_is<simple_table_t>(item) || item->getByPath<TableLit_t>()) { 1981 if (ast_is<simple_table_t>(item) || item->getByPath<TableLit_t>()) {
1966 auto subPairs = destructFromExp(pair, optional); 1982 auto subPairs = destructFromExp(pair, optional);
1967 for (auto& p : subPairs) { 1983 for (auto& p : subPairs) {
1968 pairs.push_back({p.target, p.targetVar, 1984 if (sep) p.structure->items.push_front(sep);
1969 '[' + std::to_string(index) + ']' + sep + p.structure, 1985 p.structure->items.push_front(
1970 p.defVal}); 1986 toAst<Exp_t>(std::to_string(index), p.target));
1987 pairs.push_back(p);
1971 } 1988 }
1972 } else { 1989 } else {
1973 auto exp = static_cast<Exp_t*>(pair); 1990 auto exp = static_cast<Exp_t*>(pair);
1974 auto varName = singleVariableFrom(exp, false); 1991 auto varName = singleVariableFrom(exp, false);
1975 if (varName == "_"sv) break; 1992 if (varName == "_"sv) break;
1993 auto chain = exp->new_ptr<ChainValue_t>();
1994 chain->items.push_back(toAst<Exp_t>(std::to_string(index), exp));
1976 pairs.push_back({exp, 1995 pairs.push_back({exp,
1977 varName, 1996 varName,
1978 '[' + std::to_string(index) + ']', 1997 chain,
1979 nullptr}); 1998 nullptr});
1980 } 1999 }
1981 break; 2000 break;
@@ -1983,38 +2002,55 @@ private:
1983 case id<variable_pair_t>(): { 2002 case id<variable_pair_t>(): {
1984 auto vp = static_cast<variable_pair_t*>(pair); 2003 auto vp = static_cast<variable_pair_t*>(pair);
1985 auto name = _parser.toString(vp->name); 2004 auto name = _parser.toString(vp->name);
1986 pairs.push_back({toAst<Exp_t>(name, vp).get(), name, '.' + name, nullptr}); 2005 auto chain = toAst<ChainValue_t>('.' + name, vp->name);
2006 pairs.push_back({toAst<Exp_t>(name, vp).get(),
2007 name,
2008 chain,
2009 nullptr});
1987 break; 2010 break;
1988 } 2011 }
1989 case id<normal_pair_t>(): { 2012 case id<normal_pair_t>(): {
1990 auto np = static_cast<normal_pair_t*>(pair); 2013 auto np = static_cast<normal_pair_t*>(pair);
1991 std::string keyName; 2014 ast_ptr<true, ast_node> keyIndex;
1992 if (np->key) { 2015 if (np->key) {
1993 auto key = np->key->getByPath<Name_t>(); 2016 if (auto key = np->key->getByPath<Name_t>()) {
1994 if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); 2017 auto keyNameStr = _parser.toString(key);
1995 keyName = _parser.toString(key); 2018 if (LuaKeywords.find(keyNameStr) != LuaKeywords.end()) {
1996 if (LuaKeywords.find(keyName) != LuaKeywords.end()) { 2019 keyIndex = toAst<Exp_t>('"' + keyNameStr + '"', key).get();
1997 keyName = "[\""s + keyName + "\"]"s; 2020 } else {
1998 } else { 2021 keyIndex = toAst<DotChainItem_t>('.' + keyNameStr, key).get();
1999 keyName = "."s + keyName; 2022 }
2000 } 2023 } else if (auto key = np->key->getByPath<SelfName_t>()) {
2024 auto callable = np->new_ptr<Callable_t>();
2025 callable->item.set(key);
2026 auto chainValue = np->new_ptr<ChainValue_t>();
2027 chainValue->items.push_back(callable);
2028 keyIndex = newExp(chainValue, np).get();
2029 } else if (auto key = np->key.as<Exp_t>()) {
2030 keyIndex = key;
2031 } else if (auto key = np->key.as<String_t>()) {
2032 keyIndex = newExp(key, np->key).get();
2033 } else throw std::logic_error(_info.errorMessage("unsupported key for destructuring"sv, np));
2001 } 2034 }
2002 if (auto exp = np->value.as<Exp_t>()) { 2035 if (auto exp = np->value.as<Exp_t>()) {
2003 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); 2036 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't do destructure value"sv, exp));
2004 auto item = singleValueFrom(exp)->item.get(); 2037 auto item = singleValueFrom(exp)->item.get();
2005 if (ast_is<simple_table_t>(item) || item->getByPath<TableLit_t>()) { 2038 if (ast_is<simple_table_t>(item) || item->getByPath<TableLit_t>()) {
2006 auto subPairs = destructFromExp(exp, optional); 2039 auto subPairs = destructFromExp(exp, optional);
2007 for (auto& p : subPairs) { 2040 for (auto& p : subPairs) {
2008 pairs.push_back({p.target, 2041 if (keyIndex) {
2009 p.targetVar, 2042 if (sep) p.structure->items.push_front(sep);
2010 keyName + sep + p.structure, 2043 p.structure->items.push_front(keyIndex);
2011 p.defVal}); 2044 }
2045 pairs.push_back(p);
2012 } 2046 }
2013 } else { 2047 } else {
2048 auto chain = exp->new_ptr<ChainValue_t>();
2049 if (keyIndex) chain->items.push_back(keyIndex);
2014 auto varName = singleVariableFrom(exp, false); 2050 auto varName = singleVariableFrom(exp, false);
2015 pairs.push_back({exp, 2051 pairs.push_back({exp,
2016 varName, 2052 varName,
2017 keyName, 2053 chain,
2018 nullptr}); 2054 nullptr});
2019 } 2055 }
2020 break; 2056 break;
@@ -2022,10 +2058,11 @@ private:
2022 if (np->value.is<TableBlock_t>()) { 2058 if (np->value.is<TableBlock_t>()) {
2023 auto subPairs = destructFromExp(np->value, optional); 2059 auto subPairs = destructFromExp(np->value, optional);
2024 for (auto& p : subPairs) { 2060 for (auto& p : subPairs) {
2025 pairs.push_back({p.target, 2061 if (keyIndex) {
2026 p.targetVar, 2062 if (sep) p.structure->items.push_front(sep);
2027 keyName + sep + p.structure, 2063 p.structure->items.push_front(keyIndex);
2028 p.defVal}); 2064 }
2065 pairs.push_back(p);
2029 } 2066 }
2030 } 2067 }
2031 break; 2068 break;
@@ -2035,10 +2072,9 @@ private:
2035 ++index; 2072 ++index;
2036 auto subPairs = destructFromExp(tb, optional); 2073 auto subPairs = destructFromExp(tb, optional);
2037 for (auto& p : subPairs) { 2074 for (auto& p : subPairs) {
2038 pairs.push_back({p.target, 2075 if (sep) p.structure->items.push_front(sep);
2039 p.targetVar, 2076 p.structure->items.push_front(toAst<Exp_t>(std::to_string(index), tb));
2040 '[' + std::to_string(index) + ']' + sep + p.structure, 2077 pairs.push_back(p);
2041 p.defVal});
2042 } 2078 }
2043 break; 2079 break;
2044 } 2080 }
@@ -2057,34 +2093,45 @@ private:
2057 auto varName = singleVariableFrom(exp, false); 2093 auto varName = singleVariableFrom(exp, false);
2058 pairs.push_back({exp, 2094 pairs.push_back({exp,
2059 varName, 2095 varName,
2060 '[' + std::to_string(index) + ']', 2096 toAst<ChainValue_t>('[' + std::to_string(index) + ']', value),
2061 dp->defVal}); 2097 dp->defVal});
2062 } 2098 }
2063 break; 2099 break;
2064 } 2100 }
2065 std::string keyName, valueStr; 2101 auto chain = dp->new_ptr<ChainValue_t>();
2102 std::string valueStr;
2066 if (dp->key) { 2103 if (dp->key) {
2067 auto key = dp->key->getByPath<Name_t>(); 2104 if (auto key = dp->key->getByPath<Name_t>()) {
2068 if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, dp)); 2105 auto keyName = _parser.toString(key);
2069 keyName = _parser.toString(key); 2106 if (!dp->value) valueStr = keyName;
2070 if (!dp->value) valueStr = keyName; 2107 if (LuaKeywords.find(keyName) != LuaKeywords.end()) {
2071 if (LuaKeywords.find(keyName) != LuaKeywords.end()) { 2108 chain->items.push_back(toAst<Exp_t>('"' + keyName + '"', key));
2072 keyName = "[\""s + keyName + "\"]"s; 2109 } else {
2073 } else { 2110 chain->items.push_back(toAst<DotChainItem_t>('.' + keyName, key));
2074 keyName = "."s + keyName; 2111 }
2075 } 2112 } else if (auto key = dp->key->getByPath<SelfName_t>()) {
2113 auto callable = dp->new_ptr<Callable_t>();
2114 callable->item.set(key);
2115 auto chainValue = dp->new_ptr<ChainValue_t>();
2116 chainValue->items.push_back(callable);
2117 chain->items.push_back(newExp(chainValue, dp));
2118 } else if (auto key = dp->key.as<String_t>()) {
2119 chain->items.push_back(newExp(key, dp));
2120 } else if (auto key = dp->key.as<Exp_t>()) {
2121 chain->items.push_back(key);
2122 } else throw std::logic_error(_info.errorMessage("unsupported key for destructuring"sv, dp));
2076 } 2123 }
2077 if (auto exp = dp->value.get()) { 2124 if (auto exp = dp->value.get()) {
2078 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); 2125 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp));
2079 auto varName = singleVariableFrom(exp, false); 2126 auto varName = singleVariableFrom(exp, false);
2080 pairs.push_back({exp, 2127 pairs.push_back({exp,
2081 varName, 2128 varName,
2082 keyName, 2129 chain,
2083 dp->defVal}); 2130 dp->defVal});
2084 } else { 2131 } else {
2085 pairs.push_back({toAst<Exp_t>(valueStr, dp).get(), 2132 pairs.push_back({toAst<Exp_t>(valueStr, dp).get(),
2086 valueStr, 2133 valueStr,
2087 keyName, 2134 chain,
2088 dp->defVal}); 2135 dp->defVal});
2089 } 2136 }
2090 break; 2137 break;
@@ -2093,6 +2140,9 @@ private:
2093 auto mp = static_cast<meta_default_pair_t*>(pair); 2140 auto mp = static_cast<meta_default_pair_t*>(pair);
2094 auto newPair = pair->new_ptr<default_pair_t>(); 2141 auto newPair = pair->new_ptr<default_pair_t>();
2095 if (mp->key) { 2142 if (mp->key) {
2143 if (!ast_is<Variable_t, Name_t>(mp->key)) {
2144 throw std::logic_error(_info.errorMessage("destructuring with metatable accessed by expression is not supported."sv, mp->key));
2145 }
2096 auto key = _parser.toString(mp->key); 2146 auto key = _parser.toString(mp->key);
2097 _buf << "__"sv << key; 2147 _buf << "__"sv << key;
2098 auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); 2148 auto newKey = toAst<KeyName_t>(clearBuf(), mp->key);
@@ -2145,14 +2195,16 @@ private:
2145 if (!subMetaDestruct->values.empty()) { 2195 if (!subMetaDestruct->values.empty()) {
2146 auto simpleValue = subMetaDestruct->new_ptr<SimpleValue_t>(); 2196 auto simpleValue = subMetaDestruct->new_ptr<SimpleValue_t>();
2147 simpleValue->value.set(subMetaDestruct); 2197 simpleValue->value.set(subMetaDestruct);
2148 auto value = subMetaDestruct->new_ptr<Value_t>(); 2198 auto subPairs = destructFromExp(newExp(simpleValue, subMetaDestruct), optional);
2149 value->item.set(simpleValue);
2150 auto subPairs = destructFromExp(newExp(value, subMetaDestruct), optional);
2151 for (const auto& p : subPairs) { 2199 for (const auto& p : subPairs) {
2152 pairs.push_back({p.target, 2200 if (!p.structure->items.empty()) {
2153 p.targetVar, 2201 if (sep) p.structure->items.push_front(sep);
2154 ".#"s + (p.structure.empty() ? Empty : sep + p.structure), 2202 }
2155 p.defVal}); 2203 auto mt = p.structure->new_ptr<Metatable_t>();
2204 auto dot = mt->new_ptr<DotChainItem_t>();
2205 dot->name.set(mt);
2206 p.structure->items.push_front(dot);
2207 pairs.push_back(p);
2156 } 2208 }
2157 } 2209 }
2158 return pairs; 2210 return pairs;
@@ -2258,6 +2310,12 @@ private:
2258 case id<Exp_t>(): 2310 case id<Exp_t>():
2259 newPair->key.set(mp->key); 2311 newPair->key.set(mp->key);
2260 break; 2312 break;
2313 case id<String_t>(): {
2314 auto value = mp->new_ptr<Value_t>();
2315 value->item.set(mp->key);
2316 newPair->key.set(newExp(value, mp));
2317 break;
2318 }
2261 default: YUEE("AST node mismatch", mp->key); break; 2319 default: YUEE("AST node mismatch", mp->key); break;
2262 } 2320 }
2263 } 2321 }
@@ -2289,9 +2347,7 @@ private:
2289 } 2347 }
2290 auto simpleValue = tab->new_ptr<SimpleValue_t>(); 2348 auto simpleValue = tab->new_ptr<SimpleValue_t>();
2291 simpleValue->value.set(tab); 2349 simpleValue->value.set(tab);
2292 auto value = tab->new_ptr<Value_t>(); 2350 auto pairs = destructFromExp(newExp(simpleValue, expr), optional);
2293 value->item.set(simpleValue);
2294 auto pairs = destructFromExp(newExp(value, expr), optional);
2295 if (pairs.empty()) { 2351 if (pairs.empty()) {
2296 throw std::logic_error(_info.errorMessage("expect items to be destructured"sv, tab)); 2352 throw std::logic_error(_info.errorMessage("expect items to be destructured"sv, tab));
2297 } 2353 }
@@ -2299,15 +2355,13 @@ private:
2299 if (!varDefOnly) { 2355 if (!varDefOnly) {
2300 if (*j == nil) { 2356 if (*j == nil) {
2301 for (auto& item : destruct.items) { 2357 for (auto& item : destruct.items) {
2302 item.structure.clear(); 2358 item.structure = nullptr;
2303 } 2359 }
2304 } else if (tab == subMetaDestruct.get()) { 2360 } else if (tab == subMetaDestruct.get()) {
2305 auto p = destruct.value.get(); 2361 auto p = destruct.value.get();
2306 auto chainValue = toAst<ChainValue_t>("getmetatable()", p); 2362 auto chainValue = toAst<ChainValue_t>("getmetatable()", p);
2307 static_cast<Invoke_t*>(chainValue->items.back())->args.push_back(destruct.value); 2363 static_cast<Invoke_t*>(chainValue->items.back())->args.push_back(destruct.value);
2308 auto value = p->new_ptr<Value_t>(); 2364 auto exp = newExp(chainValue, p);
2309 value->item.set(chainValue);
2310 auto exp = newExp(value, p);
2311 destruct.value.set(exp); 2365 destruct.value.set(exp);
2312 destruct.valueVar.clear(); 2366 destruct.valueVar.clear();
2313 } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) { 2367 } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) {
@@ -2318,9 +2372,7 @@ private:
2318 callable->item.set(parens); 2372 callable->item.set(parens);
2319 auto chainValue = p->new_ptr<ChainValue_t>(); 2373 auto chainValue = p->new_ptr<ChainValue_t>();
2320 chainValue->items.push_back(callable); 2374 chainValue->items.push_back(callable);
2321 auto value = p->new_ptr<Value_t>(); 2375 auto exp = newExp(chainValue, p);
2322 value->item.set(chainValue);
2323 auto exp = newExp(value, p);
2324 destruct.value.set(exp); 2376 destruct.value.set(exp);
2325 destruct.valueVar.clear(); 2377 destruct.valueVar.clear();
2326 } 2378 }
@@ -2346,6 +2398,51 @@ private:
2346 newAssign->action.set(assign); 2398 newAssign->action.set(assign);
2347 newAssignment = newAssign; 2399 newAssignment = newAssign;
2348 } 2400 }
2401 if (!varDefOnly) {
2402 pushScope();
2403 for (auto& des : destructs) {
2404 for (const auto& item : des.items) {
2405 for (auto node : item.structure->items.objects()) {
2406 if (auto exp = ast_cast<Exp_t>(node)) {
2407 if (auto value = simpleSingleValueFrom(node)) {
2408 if (ast_is<Num_t, const_value_t>(value->value)) {
2409 continue;
2410 }
2411 }
2412 if (auto value = singleValueFrom(exp); !value || !value->item.is<String_t>()) {
2413 auto var = singleVariableFrom(exp, false);
2414 if (var.empty()) {
2415 if (!des.inlineAssignment) {
2416 des.inlineAssignment = x->new_ptr<ExpListAssign_t>();
2417 auto expList = x->new_ptr<ExpList_t>();
2418 des.inlineAssignment->expList.set(expList);
2419 auto assign = x->new_ptr<Assign_t>();
2420 des.inlineAssignment->action.set(assign);
2421 }
2422 auto assignList = des.inlineAssignment->expList.get();
2423 auto assign = des.inlineAssignment->action.to<Assign_t>();
2424 auto tmpVar = getUnusedName("_tmp_"sv);
2425 addToScope(tmpVar);
2426 auto tmpExp = toAst<Exp_t>(tmpVar, exp);
2427 assignList->exprs.push_back(tmpExp);
2428 auto vExp = exp->new_ptr<Exp_t>();
2429 vExp->pipeExprs.dup(exp->pipeExprs);
2430 vExp->opValues.dup(exp->opValues);
2431 vExp->nilCoalesed.set(exp->nilCoalesed);
2432 exp->pipeExprs.clear();
2433 exp->pipeExprs.dup(tmpExp->pipeExprs);
2434 exp->opValues.clear();
2435 exp->opValues.dup(tmpExp->opValues);
2436 exp->nilCoalesed = tmpExp->nilCoalesed;
2437 assign->values.push_back(vExp);
2438 }
2439 }
2440 }
2441 }
2442 }
2443 }
2444 popScope();
2445 }
2349 return {std::move(destructs), newAssignment}; 2446 return {std::move(destructs), newAssignment};
2350 } 2447 }
2351 2448
@@ -2385,9 +2482,7 @@ private:
2385 tmpChain->items.push_back(item); 2482 tmpChain->items.push_back(item);
2386 } 2483 }
2387 } 2484 }
2388 auto value = x->new_ptr<Value_t>(); 2485 auto exp = newExp(tmpChain, x);
2389 value->item.set(tmpChain);
2390 auto exp = newExp(value, x);
2391 auto objVar = getUnusedName("_obj_"sv); 2486 auto objVar = getUnusedName("_obj_"sv);
2392 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 2487 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2393 newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); 2488 newAssignment->expList.set(toAst<ExpList_t>(objVar, x));
@@ -2518,9 +2613,7 @@ private:
2518 ns.clear(); 2613 ns.clear();
2519 auto simpleValue = x->new_ptr<SimpleValue_t>(); 2614 auto simpleValue = x->new_ptr<SimpleValue_t>();
2520 simpleValue->value.set(newIf); 2615 simpleValue->value.set(newIf);
2521 auto value = x->new_ptr<Value_t>(); 2616 auto exp = newExp(simpleValue, x);
2522 value->item.set(simpleValue);
2523 auto exp = newExp(value, x);
2524 auto expList = x->new_ptr<ExpList_t>(); 2617 auto expList = x->new_ptr<ExpList_t>();
2525 expList->exprs.push_back(exp); 2618 expList->exprs.push_back(exp);
2526 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 2619 auto expListAssign = x->new_ptr<ExpListAssign_t>();
@@ -3129,9 +3222,7 @@ private:
3129 funLit->body.set(body); 3222 funLit->body.set(body);
3130 auto simpleValue = x->new_ptr<SimpleValue_t>(); 3223 auto simpleValue = x->new_ptr<SimpleValue_t>();
3131 simpleValue->value.set(funLit); 3224 simpleValue->value.set(funLit);
3132 auto value = x->new_ptr<Value_t>(); 3225 arg = newExp(simpleValue, x);
3133 value->item.set(simpleValue);
3134 arg = newExp(value, x);
3135 } 3226 }
3136 if (isChainValueCall(backcall->value)) { 3227 if (isChainValueCall(backcall->value)) {
3137 auto last = backcall->value->items.back(); 3228 auto last = backcall->value->items.back();
@@ -3164,9 +3255,7 @@ private:
3164 auto newStmt = x->new_ptr<Statement_t>(); 3255 auto newStmt = x->new_ptr<Statement_t>();
3165 { 3256 {
3166 auto chainValue = backcall->value.get(); 3257 auto chainValue = backcall->value.get();
3167 auto value = x->new_ptr<Value_t>(); 3258 auto exp = newExp(chainValue, x);
3168 value->item.set(chainValue);
3169 auto exp = newExp(value, x);
3170 auto expList = x->new_ptr<ExpList_t>(); 3259 auto expList = x->new_ptr<ExpList_t>();
3171 expList->exprs.push_back(exp); 3260 expList->exprs.push_back(exp);
3172 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 3261 auto expListAssign = x->new_ptr<ExpListAssign_t>();
@@ -3329,9 +3418,7 @@ private:
3329 } else { 3418 } else {
3330 auto simpleValue = x->new_ptr<SimpleValue_t>(); 3419 auto simpleValue = x->new_ptr<SimpleValue_t>();
3331 simpleValue->value.set(last->content); 3420 simpleValue->value.set(last->content);
3332 auto value = x->new_ptr<Value_t>(); 3421 auto exp = newExp(simpleValue, x);
3333 value->item.set(simpleValue);
3334 auto exp = newExp(value, x);
3335 assign->values.push_back(exp); 3422 assign->values.push_back(exp);
3336 } 3423 }
3337 newAssignment->action.set(assign); 3424 newAssignment->action.set(assign);
@@ -3857,9 +3944,7 @@ private:
3857 callable->item.set(parens); 3944 callable->item.set(parens);
3858 auto chainValue = x->new_ptr<ChainValue_t>(); 3945 auto chainValue = x->new_ptr<ChainValue_t>();
3859 chainValue->items.push_back(callable); 3946 chainValue->items.push_back(callable);
3860 auto value = x->new_ptr<Value_t>(); 3947 auto exp = newExp(chainValue, x);
3861 value->item.set(chainValue);
3862 auto exp = newExp(value, x);
3863 auto assignment = x->new_ptr<ExpListAssign_t>(); 3948 auto assignment = x->new_ptr<ExpListAssign_t>();
3864 assignment->expList.set(assignList); 3949 assignment->expList.set(assignList);
3865 auto assign = x->new_ptr<Assign_t>(); 3950 auto assign = x->new_ptr<Assign_t>();
@@ -3949,9 +4034,7 @@ private:
3949 if (!newObj.empty()) { 4034 if (!newObj.empty()) {
3950 objVar = newObj; 4035 objVar = newObj;
3951 } else { 4036 } else {
3952 auto value = x->new_ptr<Value_t>(); 4037 auto exp = newExp(chainValue, x);
3953 value->item.set(chainValue);
3954 auto exp = newExp(value, x);
3955 auto assign = x->new_ptr<Assign_t>(); 4038 auto assign = x->new_ptr<Assign_t>();
3956 assign->values.push_back(exp); 4039 assign->values.push_back(exp);
3957 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 4040 auto expListAssign = x->new_ptr<ExpListAssign_t>();
@@ -3981,9 +4064,7 @@ private:
3981 } 4064 }
3982 objVar = getUnusedName("_obj_"sv); 4065 objVar = getUnusedName("_obj_"sv);
3983 } 4066 }
3984 auto value = x->new_ptr<Value_t>(); 4067 auto exp = newExp(partOne, x);
3985 value->item.set(partOne);
3986 auto exp = newExp(value, x);
3987 auto assign = x->new_ptr<Assign_t>(); 4068 auto assign = x->new_ptr<Assign_t>();
3988 assign->values.push_back(exp); 4069 assign->values.push_back(exp);
3989 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 4070 auto expListAssign = x->new_ptr<ExpListAssign_t>();
@@ -4004,9 +4085,7 @@ private:
4004 transformChainValue(partTwo, temp, ExpUsage::Common); 4085 transformChainValue(partTwo, temp, ExpUsage::Common);
4005 break; 4086 break;
4006 case ExpUsage::Assignment: { 4087 case ExpUsage::Assignment: {
4007 auto value = x->new_ptr<Value_t>(); 4088 auto exp = newExp(partTwo, x);
4008 value->item.set(partTwo);
4009 auto exp = newExp(value, x);
4010 auto assign = x->new_ptr<Assign_t>(); 4089 auto assign = x->new_ptr<Assign_t>();
4011 assign->values.push_back(exp); 4090 assign->values.push_back(exp);
4012 auto assignment = x->new_ptr<ExpListAssign_t>(); 4091 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -4017,9 +4096,7 @@ private:
4017 } 4096 }
4018 case ExpUsage::Return: 4097 case ExpUsage::Return:
4019 case ExpUsage::Closure: { 4098 case ExpUsage::Closure: {
4020 auto value = x->new_ptr<Value_t>(); 4099 auto exp = newExp(partTwo, x);
4021 value->item.set(partTwo);
4022 auto exp = newExp(value, x);
4023 auto ret = x->new_ptr<Return_t>(); 4100 auto ret = x->new_ptr<Return_t>();
4024 auto expListLow = x->new_ptr<ExpListLow_t>(); 4101 auto expListLow = x->new_ptr<ExpListLow_t>();
4025 expListLow->exprs.push_back(exp); 4102 expListLow->exprs.push_back(exp);
@@ -4095,9 +4172,7 @@ private:
4095 auto baseVar = getUnusedName("_base_"sv); 4172 auto baseVar = getUnusedName("_base_"sv);
4096 auto fnVar = getUnusedName("_fn_"sv); 4173 auto fnVar = getUnusedName("_fn_"sv);
4097 { 4174 {
4098 auto value = x->new_ptr<Value_t>(); 4175 auto exp = newExp(baseChain, x);
4099 value->item.set(baseChain);
4100 auto exp = newExp(value, x);
4101 auto assign = x->new_ptr<Assign_t>(); 4176 auto assign = x->new_ptr<Assign_t>();
4102 assign->values.push_back(exp); 4177 assign->values.push_back(exp);
4103 auto assignment = x->new_ptr<ExpListAssign_t>(); 4178 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -4183,26 +4258,124 @@ private:
4183 for (auto it = chainList.begin(); it != opIt; ++it) { 4258 for (auto it = chainList.begin(); it != opIt; ++it) {
4184 chain->items.push_back(*it); 4259 chain->items.push_back(*it);
4185 } 4260 }
4186 auto value = x->new_ptr<Value_t>(); 4261 {
4187 value->item.set(chain); 4262 auto exp = newExp(chain, x);
4188 auto exp = newExp(value, x); 4263 chain = toAst<ChainValue_t>("getmetatable()"sv, x);
4189 4264 ast_to<Invoke_t>(chain->items.back())->args.push_back(exp);
4190 chain = toAst<ChainValue_t>("getmetatable()"sv, x); 4265 }
4191 ast_to<Invoke_t>(chain->items.back())->args.push_back(exp);
4192 switch ((*opIt)->getId()) { 4266 switch ((*opIt)->getId()) {
4193 case id<ColonChainItem_t>(): { 4267 case id<ColonChainItem_t>(): {
4194 auto colon = static_cast<ColonChainItem_t*>(*opIt); 4268 auto colon = static_cast<ColonChainItem_t*>(*opIt);
4195 auto meta = colon->name.to<Metamethod_t>(); 4269 auto meta = colon->name.to<Metamethod_t>();
4196 auto newColon = toAst<ColonChainItem_t>("\\__"s + _parser.toString(meta->name), x); 4270 switch (meta->item->getId()) {
4197 chain->items.push_back(newColon); 4271 case id<Name_t>(): {
4272 auto newColon = toAst<ColonChainItem_t>("\\__"s + _parser.toString(meta->item), x);
4273 chain->items.push_back(newColon);
4274 break;
4275 }
4276 case id<String_t>():
4277 case id<Exp_t>(): {
4278 str_list temp;
4279 std::string* funcStart = nullptr;
4280 if (usage == ExpUsage::Closure) {
4281 _enableReturn.push(true);
4282 pushAnonVarArg();
4283 funcStart = &temp.emplace_back();
4284 pushScope();
4285 } else if (usage != ExpUsage::Return) {
4286 temp.push_back(indent() + "do"s + nll(x));
4287 pushScope();
4288 }
4289 auto var = getUnusedName("_obj_"sv);
4290 auto target = toAst<Exp_t>(var, x);
4291 {
4292 auto assignment = assignmentFrom(target, newExp(chain, x), x);
4293 transformAssignment(assignment, temp);
4294 }
4295 auto newChain = toAst<ChainValue_t>(var, x);
4296 if (auto str = meta->item.as<String_t>()) {
4297 newChain->items.push_back(newExp(str, x));
4298 } else {
4299 newChain->items.push_back(meta->item);
4300 }
4301 auto newChainExp = newExp(newChain, x);
4302 for (auto it = ++opIt; it != chainList.end(); ++it) {
4303 newChain->items.push_back(*it);
4304 }
4305 auto last = newChain->items.back();
4306 if (ast_is<Invoke_t, InvokeArgs_t>(last)) {
4307 if (auto invoke = ast_cast<InvokeArgs_t>(last)) {
4308 invoke->args.push_front(target);
4309 } else {
4310 ast_to<Invoke_t>(last)->args.push_front(target);
4311 }
4312 }
4313 switch (usage) {
4314 case ExpUsage::Closure: {
4315 auto returnNode = x->new_ptr<Return_t>();
4316 auto values = x->new_ptr<ExpListLow_t>();
4317 values->exprs.push_back(newChainExp);
4318 returnNode->valueList.set(values);
4319 transformReturn(returnNode, temp);
4320 popScope();
4321 *funcStart = anonFuncStart() + nll(x);
4322 temp.push_back(indent() + anonFuncEnd());
4323 popAnonVarArg();
4324 _enableReturn.pop();
4325 break;
4326 }
4327 case ExpUsage::Return: {
4328 auto returnNode = x->new_ptr<Return_t>();
4329 auto values = x->new_ptr<ExpListLow_t>();
4330 values->exprs.push_back(newChainExp);
4331 returnNode->valueList.set(values);
4332 transformReturn(returnNode, temp);
4333 break;
4334 }
4335 case ExpUsage::Assignment: {
4336 auto assignment = x->new_ptr<ExpListAssign_t>();
4337 assignment->expList.set(assignList);
4338 auto assign = x->new_ptr<Assign_t>();
4339 assign->values.push_back(newChainExp);
4340 assignment->action.set(assign);
4341 transformAssignment(assignment, temp);
4342 popScope();
4343 temp.push_back(indent() + "end"s + nlr(x));
4344 break;
4345 }
4346 case ExpUsage::Common:
4347 transformExp(newChainExp, temp, usage);
4348 popScope();
4349 temp.push_back(indent() + "end"s + nlr(x));
4350 break;
4351 }
4352 out.push_back(join(temp));
4353 return true;
4354 }
4355 default: YUEE("AST node mismatch", meta->item); break;
4356 }
4198 break; 4357 break;
4199 } 4358 }
4200 case id<DotChainItem_t>(): { 4359 case id<DotChainItem_t>(): {
4201 auto dot = static_cast<DotChainItem_t*>(*opIt); 4360 auto dot = static_cast<DotChainItem_t*>(*opIt);
4202 if (dot->name.is<Metatable_t>()) break; 4361 if (dot->name.is<Metatable_t>()) break;
4203 auto meta = dot->name.to<Metamethod_t>(); 4362 auto meta = dot->name.to<Metamethod_t>();
4204 auto newDot = toAst<DotChainItem_t>(".__"s + _parser.toString(meta->name), x); 4363 switch (meta->item->getId()) {
4205 chain->items.push_back(newDot); 4364 case id<Name_t>(): {
4365 auto newDot = toAst<DotChainItem_t>(".__"s + _parser.toString(meta->item), x);
4366 chain->items.push_back(newDot);
4367 break;
4368 }
4369 case id<Exp_t>():
4370 chain->items.push_back(meta->item);
4371 break;
4372 case id<String_t>(): {
4373 auto str = static_cast<String_t*>(meta->item.get());
4374 chain->items.push_back(newExp(str, x));
4375 break;
4376 }
4377 default: YUEE("AST node mismatch", meta->item); break;
4378 }
4206 break; 4379 break;
4207 } 4380 }
4208 } 4381 }
@@ -4276,9 +4449,7 @@ private:
4276 for (auto i = chainList.begin(); i != current; ++i) { 4449 for (auto i = chainList.begin(); i != current; ++i) {
4277 chainValue->items.push_back(*i); 4450 chainValue->items.push_back(*i);
4278 } 4451 }
4279 auto value = x->new_ptr<Value_t>(); 4452 auto exp = newExp(chainValue, x);
4280 value->item.set(chainValue);
4281 auto exp = newExp(value, x);
4282 callVar = singleVariableFrom(exp, true); 4453 callVar = singleVariableFrom(exp, true);
4283 if (callVar.empty()) { 4454 if (callVar.empty()) {
4284 callVar = getUnusedName("_call_"s); 4455 callVar = getUnusedName("_call_"s);
@@ -4310,9 +4481,7 @@ private:
4310 for (auto i = next; i != chainList.end(); ++i) { 4481 for (auto i = next; i != chainList.end(); ++i) {
4311 chainValue->items.push_back(*i); 4482 chainValue->items.push_back(*i);
4312 } 4483 }
4313 auto value = x->new_ptr<Value_t>(); 4484 nexp = newExp(chainValue, x);
4314 value->item.set(chainValue);
4315 nexp = newExp(value, x);
4316 auto expList = x->new_ptr<ExpList_t>(); 4485 auto expList = x->new_ptr<ExpList_t>();
4317 expList->exprs.push_back(nexp); 4486 expList->exprs.push_back(nexp);
4318 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 4487 auto expListAssign = x->new_ptr<ExpListAssign_t>();
@@ -4342,9 +4511,7 @@ private:
4342 funLit->body.set(body); 4511 funLit->body.set(body);
4343 auto simpleValue = x->new_ptr<SimpleValue_t>(); 4512 auto simpleValue = x->new_ptr<SimpleValue_t>();
4344 simpleValue->value.set(funLit); 4513 simpleValue->value.set(funLit);
4345 auto value = x->new_ptr<Value_t>(); 4514 auto exp = newExp(simpleValue, x);
4346 value->item.set(simpleValue);
4347 auto exp = newExp(value, x);
4348 auto paren = x->new_ptr<Parens_t>(); 4515 auto paren = x->new_ptr<Parens_t>();
4349 paren->expr.set(exp); 4516 paren->expr.set(exp);
4350 auto callable = x->new_ptr<Callable_t>(); 4517 auto callable = x->new_ptr<Callable_t>();
@@ -4679,9 +4846,7 @@ private:
4679 for (; it != chainList.end(); ++it) { 4846 for (; it != chainList.end(); ++it) {
4680 newChain->items.push_back(*it); 4847 newChain->items.push_back(*it);
4681 } 4848 }
4682 auto value = x->new_ptr<Value_t>(); 4849 exp = newExp(newChain, x);
4683 value->item.set(newChain);
4684 exp = newExp(value, x);
4685 } 4850 }
4686 if (usage == ExpUsage::Common) { 4851 if (usage == ExpUsage::Common) {
4687 auto expList = x->new_ptr<ExpList_t>(); 4852 auto expList = x->new_ptr<ExpList_t>();
@@ -4961,9 +5126,7 @@ private:
4961 callable->item.set(selfName); 5126 callable->item.set(selfName);
4962 auto chainValue = x->new_ptr<ChainValue_t>(); 5127 auto chainValue = x->new_ptr<ChainValue_t>();
4963 chainValue->items.push_back(callable); 5128 chainValue->items.push_back(callable);
4964 auto value = x->new_ptr<Value_t>(); 5129 auto exp = newExp(chainValue, key);
4965 value->item.set(chainValue);
4966 auto exp = newExp(value, key);
4967 chainItem = exp.get(); 5130 chainItem = exp.get();
4968 } 5131 }
4969 chainValue->items.push_back(chainItem); 5132 chainValue->items.push_back(chainItem);
@@ -5034,7 +5197,7 @@ private:
5034 case id<meta_variable_pair_t>(): { 5197 case id<meta_variable_pair_t>(): {
5035 auto metaVarPair = static_cast<meta_variable_pair_t*>(item); 5198 auto metaVarPair = static_cast<meta_variable_pair_t*>(item);
5036 auto nameStr = _parser.toString(metaVarPair->name); 5199 auto nameStr = _parser.toString(metaVarPair->name);
5037 auto assignment = toAst<ExpListAssign_t>(tableVar + '.' + nameStr + "#="s + nameStr, item); 5200 auto assignment = toAst<ExpListAssign_t>(tableVar + ".<"s + nameStr + ">="s + nameStr, item);
5038 transformAssignment(assignment, temp); 5201 transformAssignment(assignment, temp);
5039 break; 5202 break;
5040 } 5203 }
@@ -5051,8 +5214,10 @@ private:
5051 break; 5214 break;
5052 } 5215 }
5053 case id<Exp_t>(): { 5216 case id<Exp_t>(): {
5054 auto dotItem = toAst<DotChainItem_t>(".#"sv, key); 5217 auto mt = key->new_ptr<Metatable_t>();
5055 chainValue->items.push_back(dotItem); 5218 auto dot = mt->new_ptr<DotChainItem_t>();
5219 dot->name.set(mt);
5220 chainValue->items.push_back(dot);
5056 chainValue->items.push_back(key); 5221 chainValue->items.push_back(key);
5057 break; 5222 break;
5058 } 5223 }
@@ -5158,6 +5323,11 @@ private:
5158 case id<Exp_t>(): 5323 case id<Exp_t>():
5159 newPair->key.set(mp->key); 5324 newPair->key.set(mp->key);
5160 break; 5325 break;
5326 case id<String_t>(): {
5327 auto str = static_cast<String_t*>(mp->key.get());
5328 newPair->key.set(newExp(str, mp));
5329 break;
5330 }
5161 default: YUEE("AST node mismatch", mp->key); break; 5331 default: YUEE("AST node mismatch", mp->key); break;
5162 } 5332 }
5163 newPair->value.set(mp->value); 5333 newPair->value.set(mp->value);
@@ -5504,9 +5674,7 @@ private:
5504 for (auto& pair : destructPairs) { 5674 for (auto& pair : destructPairs) {
5505 auto sValue = x->new_ptr<SimpleValue_t>(); 5675 auto sValue = x->new_ptr<SimpleValue_t>();
5506 sValue->value.set(pair.first); 5676 sValue->value.set(pair.first);
5507 auto value = x->new_ptr<Value_t>(); 5677 auto exp = newExp(sValue, x);
5508 value->item.set(sValue);
5509 auto exp = newExp(value, x);
5510 auto expList = x->new_ptr<ExpList_t>(); 5678 auto expList = x->new_ptr<ExpList_t>();
5511 expList->exprs.push_back(exp); 5679 expList->exprs.push_back(exp);
5512 auto assign = x->new_ptr<Assign_t>(); 5680 auto assign = x->new_ptr<Assign_t>();
@@ -5918,18 +6086,26 @@ private:
5918 transformExp(static_cast<Exp_t*>(key), temp, ExpUsage::Closure); 6086 transformExp(static_cast<Exp_t*>(key), temp, ExpUsage::Closure);
5919 temp.back() = (temp.back().front() == '[' ? "[ "s : "["s) + temp.back() + ']'; 6087 temp.back() = (temp.back().front() == '[' ? "[ "s : "["s) + temp.back() + ']';
5920 break; 6088 break;
5921 case id<DoubleString_t>(): 6089 case id<String_t>(): {
5922 transformDoubleString(static_cast<DoubleString_t*>(key), temp); 6090 auto strNode = static_cast<String_t*>(key);
5923 temp.back() = '[' + temp.back() + ']'; 6091 auto str = strNode->str.get();
5924 break; 6092 switch (str->getId()) {
5925 case id<SingleString_t>(): 6093 case id<DoubleString_t>():
5926 transformSingleString(static_cast<SingleString_t*>(key), temp); 6094 transformDoubleString(static_cast<DoubleString_t*>(str), temp);
5927 temp.back() = '[' + temp.back() + ']'; 6095 temp.back() = '[' + temp.back() + ']';
5928 break; 6096 break;
5929 case id<LuaString_t>(): 6097 case id<SingleString_t>():
5930 transformLuaString(static_cast<LuaString_t*>(key), temp); 6098 transformSingleString(static_cast<SingleString_t*>(str), temp);
5931 temp.back() = "[ "s + temp.back() + ']'; 6099 temp.back() = '[' + temp.back() + ']';
6100 break;
6101 case id<LuaString_t>():
6102 transformLuaString(static_cast<LuaString_t*>(str), temp);
6103 temp.back() = "[ "s + temp.back() + ']';
6104 break;
6105 default: YUEE("AST node mismatch", str); break;
6106 }
5932 break; 6107 break;
6108 }
5933 default: YUEE("AST node mismatch", key); break; 6109 default: YUEE("AST node mismatch", key); break;
5934 } 6110 }
5935 auto value = pair->value.get(); 6111 auto value = pair->value.get();
@@ -6308,6 +6484,8 @@ private:
6308 if (auto name = mtPair->key.as<Name_t>()) { 6484 if (auto name = mtPair->key.as<Name_t>()) {
6309 auto nameStr = _parser.toString(name); 6485 auto nameStr = _parser.toString(name);
6310 normal_pair->key.set(toAst<KeyName_t>("__"s + nameStr, keyValue)); 6486 normal_pair->key.set(toAst<KeyName_t>("__"s + nameStr, keyValue));
6487 } else if (auto str = mtPair->key.as<String_t>()) {
6488 normal_pair->key.set(newExp(str, str));
6311 } else { 6489 } else {
6312 normal_pair->key.set(mtPair->key); 6490 normal_pair->key.set(mtPair->key);
6313 } 6491 }
@@ -6624,9 +6802,7 @@ private:
6624 callable->item.set(name); 6802 callable->item.set(name);
6625 auto chainValue = x->new_ptr<ChainValue_t>(); 6803 auto chainValue = x->new_ptr<ChainValue_t>();
6626 chainValue->items.push_back(callable); 6804 chainValue->items.push_back(callable);
6627 auto value = x->new_ptr<Value_t>(); 6805 auto exp = newExp(chainValue, x);
6628 value->item.set(chainValue);
6629 auto exp = newExp(value, x);
6630 expList->exprs.push_back(exp); 6806 expList->exprs.push_back(exp);
6631 } 6807 }
6632 auto assignment = x->new_ptr<ExpListAssign_t>(); 6808 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -6979,18 +7155,14 @@ private:
6979 auto chainValue = x->new_ptr<ChainValue_t>(); 7155 auto chainValue = x->new_ptr<ChainValue_t>();
6980 chainValue->items.push_back(callable); 7156 chainValue->items.push_back(callable);
6981 chainValue->items.push_back(dotChainItem); 7157 chainValue->items.push_back(dotChainItem);
6982 auto value = x->new_ptr<Value_t>(); 7158 auto exp = newExp(chainValue, x);
6983 value->item.set(chainValue);
6984 auto exp = newExp(value, x);
6985 assign->values.push_back(exp); 7159 assign->values.push_back(exp);
6986 } 7160 }
6987 auto callable = x->new_ptr<Callable_t>(); 7161 auto callable = x->new_ptr<Callable_t>();
6988 callable->item.set(var); 7162 callable->item.set(var);
6989 auto chainValue = x->new_ptr<ChainValue_t>(); 7163 auto chainValue = x->new_ptr<ChainValue_t>();
6990 chainValue->items.push_back(callable); 7164 chainValue->items.push_back(callable);
6991 auto value = x->new_ptr<Value_t>(); 7165 auto exp = newExp(chainValue, x);
6992 value->item.set(chainValue);
6993 auto exp = newExp(value, x);
6994 expList->exprs.push_back(exp); 7166 expList->exprs.push_back(exp);
6995 break; 7167 break;
6996 } 7168 }
@@ -7004,18 +7176,14 @@ private:
7004 auto chainValue = x->new_ptr<ChainValue_t>(); 7176 auto chainValue = x->new_ptr<ChainValue_t>();
7005 chainValue->items.push_back(callable); 7177 chainValue->items.push_back(callable);
7006 chainValue->items.push_back(colonChain); 7178 chainValue->items.push_back(colonChain);
7007 auto value = x->new_ptr<Value_t>(); 7179 auto exp = newExp(chainValue, x);
7008 value->item.set(chainValue);
7009 auto exp = newExp(value, x);
7010 assign->values.push_back(exp); 7180 assign->values.push_back(exp);
7011 } 7181 }
7012 auto callable = x->new_ptr<Callable_t>(); 7182 auto callable = x->new_ptr<Callable_t>();
7013 callable->item.set(var); 7183 callable->item.set(var);
7014 auto chainValue = x->new_ptr<ChainValue_t>(); 7184 auto chainValue = x->new_ptr<ChainValue_t>();
7015 chainValue->items.push_back(callable); 7185 chainValue->items.push_back(callable);
7016 auto value = x->new_ptr<Value_t>(); 7186 auto exp = newExp(chainValue, x);
7017 value->item.set(chainValue);
7018 auto exp = newExp(value, x);
7019 expList->exprs.push_back(exp); 7187 expList->exprs.push_back(exp);
7020 break; 7188 break;
7021 } 7189 }
@@ -7507,9 +7675,7 @@ private:
7507 callable->item.set(name); 7675 callable->item.set(name);
7508 auto chainValue = x->new_ptr<ChainValue_t>(); 7676 auto chainValue = x->new_ptr<ChainValue_t>();
7509 chainValue->items.push_back(callable); 7677 chainValue->items.push_back(callable);
7510 auto value = x->new_ptr<Value_t>(); 7678 auto exp = newExp(chainValue, x);
7511 value->item.set(chainValue);
7512 auto exp = newExp(value, x);
7513 expList->exprs.push_back(exp); 7679 expList->exprs.push_back(exp);
7514 } 7680 }
7515 auto assignment = x->new_ptr<ExpListAssign_t>(); 7681 auto assignment = x->new_ptr<ExpListAssign_t>();
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index e5209ef..153babe 100755
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -351,7 +351,7 @@ YueParser::YueParser() {
351 351
352 unary_operator = 352 unary_operator =
353 expr('-') >> not_(set(">=") | space_one) | 353 expr('-') >> not_(set(">=") | space_one) |
354 expr('#') >> not_(':') | 354 expr('#') |
355 expr('~') >> not_(expr('=') | space_one) | 355 expr('~') >> not_(expr('=') | space_one) |
356 expr("not") >> not_(AlphaNum); 356 expr("not") >> not_(AlphaNum);
357 unary_exp = *(Space >> unary_operator) >> expo_exp; 357 unary_exp = *(Space >> unary_operator) >> expo_exp;
@@ -435,8 +435,9 @@ YueParser::YueParser() {
435 FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | 435 FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) |
436 (sym('!') >> not_(expr('='))); 436 (sym('!') >> not_(expr('=')));
437 437
438 Metatable = expr('#'); 438 meta_index = Name | Index | String;
439 Metamethod = Name >> expr('#'); 439 Metatable = expr('<') >> sym('>');
440 Metamethod = expr('<') >> Space >> meta_index >> sym('>');
440 441
441 existential_op = expr('?') >> not_(expr('?')); 442 existential_op = expr('?') >> not_(expr('?'));
442 table_appending_op = expr("[]"); 443 table_appending_op = expr("[]");
@@ -453,8 +454,8 @@ YueParser::YueParser() {
453 454
454 Index = symx('[') >> not_('[') >> Exp >> sym(']'); 455 Index = symx('[') >> not_('[') >> Exp >> sym(']');
455 ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; 456 ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op;
456 DotChainItem = symx('.') >> (Name >> not_('#') | Metatable | Metamethod); 457 DotChainItem = symx('.') >> (Name | Metatable | Metamethod);
457 ColonChainItem = (expr('\\') | expr("::")) >> ((LuaKeyword | Name) >> not_('#') | Metamethod); 458 ColonChainItem = (expr('\\') | expr("::")) >> (LuaKeyword | Name | Metamethod);
458 invoke_chain = Invoke >> -existential_op >> -ChainItems; 459 invoke_chain = Invoke >> -existential_op >> -ChainItems;
459 ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; 460 ColonChain = ColonChainItem >> -existential_op >> -invoke_chain;
460 461
@@ -542,26 +543,31 @@ YueParser::YueParser() {
542 return true; 543 return true;
543 })) >> not_(Space >> statement_appendix); 544 })) >> not_(Space >> statement_appendix);
544 545
545 variable_pair = sym(':') >> Variable >> not_('#'); 546 variable_pair = sym(':') >> Variable;
546 547
547 normal_pair = ( 548 normal_pair = (
548 KeyName | 549 KeyName |
549 sym('[') >> not_('[') >> Exp >> sym(']') | 550 sym('[') >> not_('[') >> Exp >> sym(']') |
550 Space >> DoubleString | 551 Space >> String
551 Space >> SingleString |
552 Space >> LuaString
553 ) >> 552 ) >>
554 symx(':') >> not_(':') >> 553 symx(':') >> not_(':') >>
555 (Exp | TableBlock | +SpaceBreak >> Exp); 554 (Exp | TableBlock | +SpaceBreak >> Exp);
556 555
557 default_pair = (sym(':') >> Variable >> not_('#') >> Seperator | KeyName >> symx(':') >> Seperator >> exp_not_tab | exp_not_tab >> Seperator) >> sym('=') >> Exp; 556 default_pair = (
557 sym(':') >> Variable >> Seperator |
558 KeyName >> symx(':') >> not_(':') >> Seperator >> exp_not_tab |
559 Space >> String >> symx(':') >> not_(':') >> Seperator >> exp_not_tab |
560 exp_not_tab >> Seperator) >> sym('=') >> Exp;
558 561
559 meta_variable_pair = sym(':') >> Variable >> expr('#'); 562 meta_variable_pair = sym(":<") >> Space >> Variable >> sym('>');
560 563
561 meta_normal_pair = Space >> -(Name | symx('[') >> not_('[') >> Exp >> sym(']')) >> expr("#:") >> 564 meta_normal_pair = sym('<') >> Space >> -meta_index >> sym(">:") >>
562 (Exp | TableBlock | +(SpaceBreak) >> Exp); 565 (Exp | TableBlock | +(SpaceBreak) >> Exp);
563 566
564 meta_default_pair = (sym(':') >> Variable >> expr('#') >> Seperator | Space >> -Name >> expr("#:") >> Seperator >> exp_not_tab) >> sym('=') >> Exp; 567 meta_default_pair = (
568 sym(":<") >> Space >> Variable >> sym('>') >> Seperator |
569 sym('<') >> Space >> -meta_index >> sym(">:") >> Seperator >> exp_not_tab
570 ) >> sym('=') >> Exp;
565 571
566 KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; 572 KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair;
567 KeyValueList = KeyValue >> *(sym(',') >> KeyValue); 573 KeyValueList = KeyValue >> *(sym(',') >> KeyValue);
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index dd577b4..f83f1b9 100755
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -172,6 +172,7 @@ private:
172 rule ChainItem; 172 rule ChainItem;
173 rule chain_line; 173 rule chain_line;
174 rule chain_block; 174 rule chain_block;
175 rule meta_index;
175 rule Index; 176 rule Index;
176 rule invoke_chain; 177 rule invoke_chain;
177 rule TableValue; 178 rule TableValue;