aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/yuescript/yue_compiler.cpp43
1 files changed, 39 insertions, 4 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index b9c9330..76d6b0f 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -478,11 +478,18 @@ private:
478 ast_ptr<true, Exp_t> defVal; 478 ast_ptr<true, Exp_t> defVal;
479 }; 479 };
480 480
481 enum class EmptyTableType {
482 None,
483 EmptyList,
484 EmptyTable
485 };
486
481 struct Destructure { 487 struct Destructure {
482 ast_ptr<true, ast_node> value; 488 ast_ptr<true, ast_node> value;
483 std::string valueVar; 489 std::string valueVar;
484 std::list<DestructItem> items; 490 std::list<DestructItem> items;
485 ast_ptr<false, ExpListAssign_t> inlineAssignment; 491 ast_ptr<false, ExpListAssign_t> inlineAssignment;
492 EmptyTableType emptyTableType = EmptyTableType::None;
486 }; 493 };
487 494
488 enum class ExpUsage { 495 enum class ExpUsage {
@@ -3425,10 +3432,9 @@ private:
3425 break; 3432 break;
3426 default: YUEE("AST node mismatch", destructNode); break; 3433 default: YUEE("AST node mismatch", destructNode); break;
3427 } 3434 }
3428 if (dlist->empty()) { 3435 bool emptyTablePattern = dlist->empty();
3429 if (!optional) { 3436 if (emptyTablePattern && !optional) {
3430 throw CompileError("expect items to be destructured"sv, destructNode); 3437 throw CompileError("expect items to be destructured"sv, destructNode);
3431 }
3432 } 3438 }
3433 for (auto item : *dlist) { 3439 for (auto item : *dlist) {
3434 switch (item->get_id()) { 3440 switch (item->get_id()) {
@@ -3554,6 +3560,26 @@ private:
3554 extraScope = true; 3560 extraScope = true;
3555 } 3561 }
3556 } 3562 }
3563 // Handle empty table pattern for switch matching
3564 if (emptyTablePattern) {
3565 Destructure emptyDestruct;
3566 if (!varDefOnly) {
3567 emptyDestruct.value = valueItems.back();
3568 emptyDestruct.valueVar = singleVariableFrom(emptyDestruct.value, AccessType::None);
3569 }
3570 switch (destructNode->get_id()) {
3571 case id<Comprehension_t>():
3572 emptyDestruct.emptyTableType = EmptyTableType::EmptyList;
3573 break;
3574 case id<TableLit_t>():
3575 case id<SimpleTable_t>():
3576 emptyDestruct.emptyTableType = EmptyTableType::EmptyTable;
3577 break;
3578 default:
3579 break;
3580 }
3581 destructs.push_back(std::move(emptyDestruct));
3582 }
3557 TableLit_t* tabs[] = {subDestruct.get(), subMetaDestruct.get()}; 3583 TableLit_t* tabs[] = {subDestruct.get(), subMetaDestruct.get()};
3558 for (auto tab : tabs) { 3584 for (auto tab : tabs) {
3559 if (!tab->values.empty()) { 3585 if (!tab->values.empty()) {
@@ -12129,6 +12155,15 @@ private:
12129 continue; 12155 continue;
12130 } 12156 }
12131 const auto& destruct = std::get<Destructure>(des); 12157 const auto& destruct = std::get<Destructure>(des);
12158 // Handle empty table pattern
12159 if (destruct.emptyTableType != EmptyTableType::None) {
12160 if (destruct.emptyTableType == EmptyTableType::EmptyList) {
12161 conds.push_back('#' + objVar + " == 0");
12162 } else {
12163 conds.push_back(globalVar("next"sv, branch, AccessType::Read) + '(' + objVar + ") == nil");
12164 }
12165 continue;
12166 }
12132 for (const auto& item : destruct.items) { 12167 for (const auto& item : destruct.items) {
12133 if (!item.defVal) { 12168 if (!item.defVal) {
12134 if (!isAssignable(item.target)) { 12169 if (!isAssignable(item.target)) {