aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-11-21 16:56:43 +0800
committerLi Jin <dragon-fly@qq.com>2022-11-21 16:56:43 +0800
commit58cf1a70971ad37ef9260aa93851e92fd6e4c1ce (patch)
treefbf8e3ae38b7b230122aac32e5461c5570dc88bf
parent8abf668c0b031c0aa81f186745eaf154aa036c8a (diff)
downloadyuescript-58cf1a70971ad37ef9260aa93851e92fd6e4c1ce.tar.gz
yuescript-58cf1a70971ad37ef9260aa93851e92fd6e4c1ce.tar.bz2
yuescript-58cf1a70971ad37ef9260aa93851e92fd6e4c1ce.zip
fix table pattern matching. confirm fixing issue #116.
-rw-r--r--spec/outputs/destructure.lua33
-rw-r--r--spec/outputs/switch.lua48
-rw-r--r--src/yuescript/yue_compiler.cpp54
-rw-r--r--src/yuescript/yue_parser.cpp17
4 files changed, 95 insertions, 57 deletions
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua
index f40a658..8953a2a 100644
--- a/spec/outputs/destructure.lua
+++ b/spec/outputs/destructure.lua
@@ -472,7 +472,8 @@ do
472 end 472 end
473 do 473 do
474 local _exp_0 = tb 474 local _exp_0 = tb
475 local _tab_0 = "table" == type(_exp_0) 475 local _tab_0 = type(_exp_0)
476 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
476 if _tab_0 then 477 if _tab_0 then
477 local name, meta_field 478 local name, meta_field
478 do 479 do
@@ -531,14 +532,17 @@ do
531 end 532 end
532 do 533 do
533 local _exp_0 = tb 534 local _exp_0 = tb
534 local _tab_0 = "table" == type(_exp_0) 535 local _tab_0 = type(_exp_0)
536 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
535 if _tab_0 then 537 if _tab_0 then
536 do 538 do
537 local _obj_0 = _exp_0.a 539 local _obj_0 = _exp_0.a
538 if _obj_0 ~= nil then 540 local _type_0 = type(_obj_0)
541 if "table" == _type_0 or "userdata" == _type_0 then
539 do 542 do
540 local _obj_1 = getmetatable(_obj_0) 543 local _obj_1 = getmetatable(_obj_0)
541 if _obj_1 ~= nil then 544 local _type_1 = type(_obj_1)
545 if "table" == _type_1 or "userdata" == _type_1 then
542 add = _obj_1.__add 546 add = _obj_1.__add
543 end 547 end
544 end 548 end
@@ -546,10 +550,12 @@ do
546 end 550 end
547 do 551 do
548 local _obj_0 = _exp_0.b 552 local _obj_0 = _exp_0.b
549 if _obj_0 ~= nil then 553 local _type_0 = type(_obj_0)
554 if "table" == _type_0 or "userdata" == _type_0 then
550 do 555 do
551 local _obj_1 = getmetatable(_obj_0) 556 local _obj_1 = getmetatable(_obj_0)
552 if _obj_1 ~= nil then 557 local _type_1 = type(_obj_1)
558 if "table" == _type_1 or "userdata" == _type_1 then
553 field = _obj_1[fieldName] 559 field = _obj_1[fieldName]
554 end 560 end
555 end 561 end
@@ -566,15 +572,18 @@ do
566 end 572 end
567 do 573 do
568 local _exp_0 = tb 574 local _exp_0 = tb
569 local _tab_0 = "table" == type(_exp_0) 575 local _tab_0 = type(_exp_0)
576 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
570 if _tab_0 then 577 if _tab_0 then
571 local _obj_0 = _exp_0 578 local _obj_0 = _exp_0
572 do 579 do
573 local _obj_1 = _obj_0.c 580 local _obj_1 = _obj_0.c
574 if _obj_1 ~= nil then 581 local _type_0 = type(_obj_1)
582 if "table" == _type_0 or "userdata" == _type_0 then
575 do 583 do
576 local _obj_2 = getmetatable(_obj_1) 584 local _obj_2 = getmetatable(_obj_1)
577 if _obj_2 ~= nil then 585 local _type_1 = type(_obj_2)
586 if "table" == _type_1 or "userdata" == _type_1 then
578 meta_field = _obj_2["abc"] 587 meta_field = _obj_2["abc"]
579 end 588 end
580 end 589 end
@@ -587,13 +596,15 @@ do
587 local _obj_1 = getmetatable(_obj_0) 596 local _obj_1 = getmetatable(_obj_0)
588 do 597 do
589 local _obj_2 = _obj_1[ [[any string]]] 598 local _obj_2 = _obj_1[ [[any string]]]
590 if _obj_2 ~= nil then 599 local _type_0 = type(_obj_2)
600 if "table" == _type_0 or "userdata" == _type_0 then
591 abc = _obj_2.d 601 abc = _obj_2.d
592 end 602 end
593 end 603 end
594 do 604 do
595 local _obj_2 = _obj_1['str'] 605 local _obj_2 = _obj_1['str']
596 if _obj_2 ~= nil then 606 local _type_0 = type(_obj_2)
607 if "table" == _type_0 or "userdata" == _type_0 then
597 def = _obj_2.e 608 def = _obj_2.e
598 end 609 end
599 end 610 end
diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua
index 4358027..3c48120 100644
--- a/spec/outputs/switch.lua
+++ b/spec/outputs/switch.lua
@@ -107,37 +107,43 @@ do
107 } 107 }
108 } 108 }
109 do 109 do
110 local _tab_0 = "table" == type(dict) 110 local _tab_0 = type(dict)
111 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
111 if _tab_0 then 112 if _tab_0 then
112 local first = dict[1] 113 local first = dict[1]
113 local one 114 local one
114 do 115 do
115 local _obj_0 = dict[2] 116 local _obj_0 = dict[2]
116 if _obj_0 ~= nil then 117 local _type_0 = type(_obj_0)
118 if "table" == _type_0 or "userdata" == _type_0 then
117 one = _obj_0[1] 119 one = _obj_0[1]
118 end 120 end
119 end 121 end
120 local two 122 local two
121 do 123 do
122 local _obj_0 = dict[2] 124 local _obj_0 = dict[2]
123 if _obj_0 ~= nil then 125 local _type_0 = type(_obj_0)
126 if "table" == _type_0 or "userdata" == _type_0 then
124 two = _obj_0[2] 127 two = _obj_0[2]
125 end 128 end
126 end 129 end
127 local three 130 local three
128 do 131 do
129 local _obj_0 = dict[2] 132 local _obj_0 = dict[2]
130 if _obj_0 ~= nil then 133 local _type_0 = type(_obj_0)
134 if "table" == _type_0 or "userdata" == _type_0 then
131 three = _obj_0[3] 135 three = _obj_0[3]
132 end 136 end
133 end 137 end
134 local c 138 local c
135 do 139 do
136 local _obj_0 = dict.a 140 local _obj_0 = dict.a
137 if _obj_0 ~= nil then 141 local _type_0 = type(_obj_0)
142 if "table" == _type_0 or "userdata" == _type_0 then
138 do 143 do
139 local _obj_1 = _obj_0.b 144 local _obj_1 = _obj_0.b
140 if _obj_1 ~= nil then 145 local _type_1 = type(_obj_1)
146 if "table" == _type_1 or "userdata" == _type_1 then
141 c = _obj_1.c 147 c = _obj_1.c
142 end 148 end
143 end 149 end
@@ -146,10 +152,12 @@ do
146 local z 152 local z
147 do 153 do
148 local _obj_0 = dict.x 154 local _obj_0 = dict.x
149 if _obj_0 ~= nil then 155 local _type_0 = type(_obj_0)
156 if "table" == _type_0 or "userdata" == _type_0 then
150 do 157 do
151 local _obj_1 = _obj_0.y 158 local _obj_1 = _obj_0.y
152 if _obj_1 ~= nil then 159 local _type_1 = type(_obj_1)
160 if "table" == _type_1 or "userdata" == _type_1 then
153 z = _obj_1.z 161 z = _obj_1.z
154 end 162 end
155 end 163 end
@@ -176,7 +184,8 @@ do
176 for _index_0 = 1, #items do 184 for _index_0 = 1, #items do
177 local item = items[_index_0] 185 local item = items[_index_0]
178 do 186 do
179 local _tab_0 = "table" == type(item) 187 local _tab_0 = type(item)
188 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
180 local _match_0 = false 189 local _match_0 = false
181 if _tab_0 then 190 if _tab_0 then
182 local x = item.x 191 local x = item.x
@@ -234,7 +243,8 @@ end
234do 243do
235 local tb = { } 244 local tb = { }
236 do 245 do
237 local _tab_0 = "table" == type(tb) 246 local _tab_0 = type(tb)
247 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
238 if _tab_0 then 248 if _tab_0 then
239 local a = tb.a 249 local a = tb.a
240 local b = tb.b 250 local b = tb.b
@@ -248,7 +258,8 @@ do
248 end 258 end
249 end 259 end
250 do 260 do
251 local _tab_0 = "table" == type(tb) 261 local _tab_0 = type(tb)
262 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
252 if _tab_0 then 263 if _tab_0 then
253 local a = tb.a 264 local a = tb.a
254 local b = tb.b 265 local b = tb.b
@@ -261,7 +272,8 @@ do
261 end 272 end
262 end 273 end
263 do 274 do
264 local _tab_0 = "table" == type(tb) 275 local _tab_0 = type(tb)
276 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
265 local _match_0 = false 277 local _match_0 = false
266 if _tab_0 then 278 if _tab_0 then
267 local a = tb.a 279 local a = tb.a
@@ -281,7 +293,8 @@ do
281 x = "abc" 293 x = "abc"
282 } 294 }
283 do 295 do
284 local _tab_0 = "table" == type(tb) 296 local _tab_0 = type(tb)
297 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
285 local _match_0 = false 298 local _match_0 = false
286 if _tab_0 then 299 if _tab_0 then
287 local x = tb.x 300 local x = tb.x
@@ -308,7 +321,8 @@ do
308 if 1 == _exp_0 then 321 if 1 == _exp_0 then
309 matched = "1" 322 matched = "1"
310 else 323 else
311 local _tab_0 = "table" == type(_exp_0) 324 local _tab_0 = type(_exp_0)
325 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
312 local _match_0 = false 326 local _match_0 = false
313 if _tab_0 then 327 if _tab_0 then
314 local x = _exp_0.x 328 local x = _exp_0.x
@@ -333,7 +347,8 @@ do
333 return "invalid" 347 return "invalid"
334 else 348 else
335 do 349 do
336 local _tab_0 = "table" == type(_exp_0) 350 local _tab_0 = type(_exp_0)
351 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
337 local _match_0 = false 352 local _match_0 = false
338 if _tab_0 then 353 if _tab_0 then
339 local a = _exp_0.a 354 local a = _exp_0.a
@@ -367,7 +382,8 @@ end
367do 382do
368 do 383 do
369 local _exp_0 = y 384 local _exp_0 = y
370 local _tab_0 = "table" == type(_exp_0) 385 local _tab_0 = type(_exp_0)
386 _tab_0 = "table" == _tab_0 or "userdata" == _tab_0
371 if _tab_0 then 387 if _tab_0 then
372 local mt = (function() 388 local mt = (function()
373 local _obj_0 = _exp_0.x 389 local _obj_0 = _exp_0.x
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 066a661..cd91c97 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -60,7 +60,7 @@ namespace yue {
60 60
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.15.14"sv; 63const std::string_view version = "0.15.15"sv;
64const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
65 65
66class YueCompilerImpl { 66class YueCompilerImpl {
@@ -1806,7 +1806,7 @@ private:
1806 case ChainType::EndWithColon: 1806 case ChainType::EndWithColon:
1807 case ChainType::MetaFieldInvocation: { 1807 case ChainType::MetaFieldInvocation: {
1808 std::string preDefine = getPreDefineLine(assignment); 1808 std::string preDefine = getPreDefineLine(assignment);
1809 transformChainValue(chainValue, out, ExpUsage::Assignment, expList); 1809 transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct);
1810 out.back().insert(0, preDefine); 1810 out.back().insert(0, preDefine);
1811 return; 1811 return;
1812 } 1812 }
@@ -1850,7 +1850,7 @@ private:
1850 newChain->items.dup(pair.structure->items); 1850 newChain->items.dup(pair.structure->items);
1851 } 1851 }
1852 auto newAssignment = assignmentFrom(pair.target, newExp(newChain, val->item), x); 1852 auto newAssignment = assignmentFrom(pair.target, newExp(newChain, val->item), x);
1853 transformAssignment(newAssignment, temp); 1853 transformAssignment(newAssignment, temp, optionalDestruct);
1854 if (pair.defVal) { 1854 if (pair.defVal) {
1855 bool isNil = false; 1855 bool isNil = false;
1856 if (auto v1 = singleValueFrom(pair.defVal)) { 1856 if (auto v1 = singleValueFrom(pair.defVal)) {
@@ -1898,7 +1898,7 @@ private:
1898 chain->items.dup(pair.structure->items); 1898 chain->items.dup(pair.structure->items);
1899 auto valueExp = newExp(chain, pair.target); 1899 auto valueExp = newExp(chain, pair.target);
1900 auto newAssignment = assignmentFrom(pair.target, valueExp, x); 1900 auto newAssignment = assignmentFrom(pair.target, valueExp, x);
1901 transformAssignment(newAssignment, temp); 1901 transformAssignment(newAssignment, temp, optionalDestruct);
1902 if (!isLocalValue) { 1902 if (!isLocalValue) {
1903 popScope(); 1903 popScope();
1904 _buf << indent() << "end"sv << nlr(x); 1904 _buf << indent() << "end"sv << nlr(x);
@@ -1986,7 +1986,7 @@ private:
1986 auto assign = x->new_ptr<Assign_t>(); 1986 auto assign = x->new_ptr<Assign_t>();
1987 assign->values.dup(valueList->exprs); 1987 assign->values.dup(valueList->exprs);
1988 newAssignment->action.set(assign); 1988 newAssignment->action.set(assign);
1989 transformAssignment(newAssignment, temp); 1989 transformAssignment(newAssignment, temp, true);
1990 } 1990 }
1991 } else { 1991 } else {
1992 auto valueList = x->new_ptr<ExpList_t>(); 1992 auto valueList = x->new_ptr<ExpList_t>();
@@ -2114,10 +2114,10 @@ private:
2114 throw std::logic_error(_info.errorMessage("default value is not supported here"sv, defVal)); 2114 throw std::logic_error(_info.errorMessage("default value is not supported here"sv, defVal));
2115 } 2115 }
2116 } 2116 }
2117 auto indexItem = toAst<Exp_t>(std::to_string(index), value);
2117 for (auto& p : subPairs) { 2118 for (auto& p : subPairs) {
2118 if (sep) p.structure->items.push_front(sep); 2119 if (sep) p.structure->items.push_front(sep);
2119 p.structure->items.push_front( 2120 p.structure->items.push_front(indexItem);
2120 toAst<Exp_t>(std::to_string(index), p.target));
2121 pairs.push_back(p); 2121 pairs.push_back(p);
2122 } 2122 }
2123 } else { 2123 } else {
@@ -2125,7 +2125,8 @@ private:
2125 auto varName = singleVariableFrom(exp, false); 2125 auto varName = singleVariableFrom(exp, false);
2126 if (varName == "_"sv) break; 2126 if (varName == "_"sv) break;
2127 auto chain = exp->new_ptr<ChainValue_t>(); 2127 auto chain = exp->new_ptr<ChainValue_t>();
2128 chain->items.push_back(toAst<Exp_t>(std::to_string(index), exp)); 2128 auto indexItem = toAst<Exp_t>(std::to_string(index), exp);
2129 chain->items.push_back(indexItem);
2129 pairs.push_back({exp, 2130 pairs.push_back({exp,
2130 varName, 2131 varName,
2131 chain, 2132 chain,
@@ -2229,9 +2230,10 @@ private:
2229 auto tb = static_cast<TableBlockIndent_t*>(pair); 2230 auto tb = static_cast<TableBlockIndent_t*>(pair);
2230 ++index; 2231 ++index;
2231 auto subPairs = destructFromExp(tb, optional); 2232 auto subPairs = destructFromExp(tb, optional);
2233 auto indexItem = toAst<Exp_t>(std::to_string(index), tb);
2232 for (auto& p : subPairs) { 2234 for (auto& p : subPairs) {
2233 if (sep) p.structure->items.push_front(sep); 2235 if (sep) p.structure->items.push_front(sep);
2234 p.structure->items.push_front(toAst<Exp_t>(std::to_string(index), tb)); 2236 p.structure->items.push_front(indexItem);
2235 pairs.push_back(p); 2237 pairs.push_back(p);
2236 } 2238 }
2237 break; 2239 break;
@@ -2290,13 +2292,13 @@ private:
2290 auto simpleValue = subMetaDestruct->new_ptr<SimpleValue_t>(); 2292 auto simpleValue = subMetaDestruct->new_ptr<SimpleValue_t>();
2291 simpleValue->value.set(subMetaDestruct); 2293 simpleValue->value.set(subMetaDestruct);
2292 auto subPairs = destructFromExp(newExp(simpleValue, subMetaDestruct), optional); 2294 auto subPairs = destructFromExp(newExp(simpleValue, subMetaDestruct), optional);
2295 auto mt = simpleValue->new_ptr<Metatable_t>();
2296 auto dot = mt->new_ptr<DotChainItem_t>();
2297 dot->name.set(mt);
2293 for (const auto& p : subPairs) { 2298 for (const auto& p : subPairs) {
2294 if (!p.structure->items.empty()) { 2299 if (!p.structure->items.empty()) {
2295 if (sep) p.structure->items.push_front(sep); 2300 if (sep) p.structure->items.push_front(sep);
2296 } 2301 }
2297 auto mt = p.structure->new_ptr<Metatable_t>();
2298 auto dot = mt->new_ptr<DotChainItem_t>();
2299 dot->name.set(mt);
2300 p.structure->items.push_front(dot); 2302 p.structure->items.push_front(dot);
2301 pairs.push_back(p); 2303 pairs.push_back(p);
2302 } 2304 }
@@ -2511,7 +2513,6 @@ private:
2511 } 2513 }
2512 } 2514 }
2513 } 2515 }
2514 popScope();
2515 for (const auto& p : destructPairs) { 2516 for (const auto& p : destructPairs) {
2516 exprs.erase(p.first); 2517 exprs.erase(p.first);
2517 values.erase(p.second); 2518 values.erase(p.second);
@@ -2529,7 +2530,6 @@ private:
2529 newAssignment = newAssign; 2530 newAssignment = newAssign;
2530 } 2531 }
2531 if (!varDefOnly) { 2532 if (!varDefOnly) {
2532 pushScope();
2533 for (auto& des : destructs) { 2533 for (auto& des : destructs) {
2534 for (const auto& item : des.items) { 2534 for (const auto& item : des.items) {
2535 for (auto node : item.structure->items.objects()) { 2535 for (auto node : item.structure->items.objects()) {
@@ -2552,7 +2552,7 @@ private:
2552 auto assignList = des.inlineAssignment->expList.get(); 2552 auto assignList = des.inlineAssignment->expList.get();
2553 auto assign = des.inlineAssignment->action.to<Assign_t>(); 2553 auto assign = des.inlineAssignment->action.to<Assign_t>();
2554 auto tmpVar = getUnusedName("_tmp_"sv); 2554 auto tmpVar = getUnusedName("_tmp_"sv);
2555 addToScope(tmpVar); 2555 forceAddToScope(tmpVar);
2556 auto tmpExp = toAst<Exp_t>(tmpVar, exp); 2556 auto tmpExp = toAst<Exp_t>(tmpVar, exp);
2557 assignList->exprs.push_back(tmpExp); 2557 assignList->exprs.push_back(tmpExp);
2558 auto vExp = exp->new_ptr<Exp_t>(); 2558 auto vExp = exp->new_ptr<Exp_t>();
@@ -2571,8 +2571,8 @@ private:
2571 } 2571 }
2572 } 2572 }
2573 } 2573 }
2574 popScope();
2575 } 2574 }
2575 popScope();
2576 return {std::move(destructs), newAssignment}; 2576 return {std::move(destructs), newAssignment};
2577 } 2577 }
2578 2578
@@ -4098,7 +4098,7 @@ private:
4098 return false; 4098 return false;
4099 } 4099 }
4100 4100
4101 bool transformChainWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { 4101 bool transformChainWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList, bool optionalDestruct) {
4102 auto opIt = std::find_if(chainList.begin(), chainList.end(), [](ast_node* node) { return ast_is<existential_op_t>(node); }); 4102 auto opIt = std::find_if(chainList.begin(), chainList.end(), [](ast_node* node) { return ast_is<existential_op_t>(node); });
4103 if (opIt != chainList.end()) { 4103 if (opIt != chainList.end()) {
4104 auto x = chainList.front(); 4104 auto x = chainList.front();
@@ -4185,7 +4185,6 @@ private:
4185 auto it = opIt; 4185 auto it = opIt;
4186 ++it; 4186 ++it;
4187 if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) { 4187 if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) {
4188
4189 if (auto invoke = ast_cast<Invoke_t>(*it)) { 4188 if (auto invoke = ast_cast<Invoke_t>(*it)) {
4190 invoke->args.push_front(toAst<Exp_t>(objVar, x)); 4189 invoke->args.push_front(toAst<Exp_t>(objVar, x));
4191 } else { 4190 } else {
@@ -4203,7 +4202,15 @@ private:
4203 expListAssign->action.set(assign); 4202 expListAssign->action.set(assign);
4204 transformAssignment(expListAssign, temp); 4203 transformAssignment(expListAssign, temp);
4205 } 4204 }
4206 _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); 4205 if (optionalDestruct) {
4206 auto typeVar = getUnusedName("_type_"sv);
4207 _buf << typeVar << "=type "sv << objVar;
4208 auto typeAssign = toAst<ExpListAssign_t>(clearBuf(), partOne);
4209 transformAssignment(typeAssign, temp);
4210 _buf << indent() << "if \"table\" == " << typeVar << " or \"userdata\" == "sv << typeVar << " then"sv << nll(x);
4211 } else {
4212 _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x);
4213 }
4207 temp.push_back(clearBuf()); 4214 temp.push_back(clearBuf());
4208 pushScope(); 4215 pushScope();
4209 auto partTwo = x->new_ptr<ChainValue_t>(); 4216 auto partTwo = x->new_ptr<ChainValue_t>();
@@ -4222,7 +4229,7 @@ private:
4222 auto assignment = x->new_ptr<ExpListAssign_t>(); 4229 auto assignment = x->new_ptr<ExpListAssign_t>();
4223 assignment->expList.set(assignList); 4230 assignment->expList.set(assignList);
4224 assignment->action.set(assign); 4231 assignment->action.set(assign);
4225 transformAssignment(assignment, temp); 4232 transformAssignment(assignment, temp, optionalDestruct);
4226 break; 4233 break;
4227 } 4234 }
4228 case ExpUsage::Return: 4235 case ExpUsage::Return:
@@ -5018,7 +5025,7 @@ private:
5018 } 5025 }
5019#endif // YUE_NO_MACRO 5026#endif // YUE_NO_MACRO
5020 5027
5021 void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool allowBlockMacroReturn = false) { 5028 void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool allowBlockMacroReturn = false, bool optionalDestruct = false) {
5022 if (isMacroChain(chainValue)) { 5029 if (isMacroChain(chainValue)) {
5023#ifndef YUE_NO_MACRO 5030#ifndef YUE_NO_MACRO
5024 ast_ptr<false, ast_node> node; 5031 ast_ptr<false, ast_node> node;
@@ -5072,7 +5079,7 @@ private:
5072 if (transformChainEndWithEOP(chainList, out, usage, assignList)) { 5079 if (transformChainEndWithEOP(chainList, out, usage, assignList)) {
5073 return; 5080 return;
5074 } 5081 }
5075 if (transformChainWithEOP(chainList, out, usage, assignList)) { 5082 if (transformChainWithEOP(chainList, out, usage, assignList, optionalDestruct)) {
5076 return; 5083 return;
5077 } 5084 }
5078 if (transformChainWithMetatable(chainList, out, usage, assignList)) { 5085 if (transformChainWithMetatable(chainList, out, usage, assignList)) {
@@ -7837,7 +7844,8 @@ private:
7837 } 7844 }
7838 tabCheckVar = getUnusedName("_tab_"); 7845 tabCheckVar = getUnusedName("_tab_");
7839 forceAddToScope(tabCheckVar); 7846 forceAddToScope(tabCheckVar);
7840 temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + globalVar("type", branch) + '(' + objVar + ')' + nll(branch)); 7847 temp.push_back(indent() + "local "s + tabCheckVar + " = "s + globalVar("type", branch) + '(' + objVar + ')' + nll(branch));
7848 temp.push_back(indent() + tabCheckVar + " = \"table\" == "s + tabCheckVar + " or \"userdata\" == "s + tabCheckVar + nll(branch));
7841 } 7849 }
7842 std::string matchVar; 7850 std::string matchVar;
7843 bool lastBranch = branches.back() == branch_ && !switchNode->lastBranch; 7851 bool lastBranch = branches.back() == branch_ && !switchNode->lastBranch;
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 3f1b9a1..24f821c 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -242,18 +242,21 @@ YueParser::YueParser() {
242 SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(SwitchList)) >> body_with("then"); 242 SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(SwitchList)) >> body_with("then");
243 SwitchElse = Space >> key("else") >> body; 243 SwitchElse = Space >> key("else") >> body;
244 244
245 SwitchBlock = *EmptyLine >> 245 SwitchBlock =
246 Advance >> Seperator >>
247 SwitchCase >>
248 *(Break >> *EmptyLine >> CheckIndent >> SwitchCase) >> 246 *(Break >> *EmptyLine >> CheckIndent >> SwitchCase) >>
249 -(Break >> *EmptyLine >> CheckIndent >> SwitchElse) >> 247 -(Break >> *EmptyLine >> CheckIndent >> SwitchElse);
250 PopIndent;
251 248
252 exp_not_tab = not_(simple_table | TableLit) >> Exp; 249 exp_not_tab = not_(simple_table | TableLit) >> Exp;
253 250
254 SwitchList = Seperator >> (and_(simple_table | TableLit) >> Exp | exp_not_tab >> *(sym(',') >> exp_not_tab)); 251 SwitchList = Seperator >> (and_(simple_table | TableLit) >> Exp | exp_not_tab >> *(sym(',') >> exp_not_tab));
255 Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) 252 Switch = Space >> key("switch") >> Exp >>
256 >> -Space >> Break >> SwitchBlock; 253 Seperator >> (
254 SwitchCase >> Space >> (
255 Break >> *EmptyLine >> CheckIndent >> SwitchCase >> SwitchBlock |
256 *SwitchCase >> -SwitchElse
257 ) |
258 SpaceBreak >> *EmptyLine >> Advance >> SwitchCase >> SwitchBlock >> PopIndent
259 ) >> SwitchBlock;
257 260
258 assignment = ExpList >> Assign; 261 assignment = ExpList >> Assign;
259 IfCond = disable_chain(disable_arg_table_block(assignment | Exp)); 262 IfCond = disable_chain(disable_arg_table_block(assignment | Exp));