From df262171918e6ecc241bff6cfcf81b097ec00533 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 26 Mar 2026 12:02:35 +0800 Subject: fix: empty table pattern in switch generates valid Lua code - Add EmptyTableType enum to distinguish [] and {} patterns - [] (empty list) generates '#x == 0' check - {} (empty table) generates 'next(x) == nil' check - Fixes issue #249 --- src/yuescript/yue_compiler.cpp | 43 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'src') 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: ast_ptr defVal; }; + enum class EmptyTableType { + None, + EmptyList, + EmptyTable + }; + struct Destructure { ast_ptr value; std::string valueVar; std::list items; ast_ptr inlineAssignment; + EmptyTableType emptyTableType = EmptyTableType::None; }; enum class ExpUsage { @@ -3425,10 +3432,9 @@ private: break; default: YUEE("AST node mismatch", destructNode); break; } - if (dlist->empty()) { - if (!optional) { - throw CompileError("expect items to be destructured"sv, destructNode); - } + bool emptyTablePattern = dlist->empty(); + if (emptyTablePattern && !optional) { + throw CompileError("expect items to be destructured"sv, destructNode); } for (auto item : *dlist) { switch (item->get_id()) { @@ -3554,6 +3560,26 @@ private: extraScope = true; } } + // Handle empty table pattern for switch matching + if (emptyTablePattern) { + Destructure emptyDestruct; + if (!varDefOnly) { + emptyDestruct.value = valueItems.back(); + emptyDestruct.valueVar = singleVariableFrom(emptyDestruct.value, AccessType::None); + } + switch (destructNode->get_id()) { + case id(): + emptyDestruct.emptyTableType = EmptyTableType::EmptyList; + break; + case id(): + case id(): + emptyDestruct.emptyTableType = EmptyTableType::EmptyTable; + break; + default: + break; + } + destructs.push_back(std::move(emptyDestruct)); + } TableLit_t* tabs[] = {subDestruct.get(), subMetaDestruct.get()}; for (auto tab : tabs) { if (!tab->values.empty()) { @@ -12129,6 +12155,15 @@ private: continue; } const auto& destruct = std::get(des); + // Handle empty table pattern + if (destruct.emptyTableType != EmptyTableType::None) { + if (destruct.emptyTableType == EmptyTableType::EmptyList) { + conds.push_back('#' + objVar + " == 0"); + } else { + conds.push_back(globalVar("next"sv, branch, AccessType::Read) + '(' + objVar + ") == nil"); + } + continue; + } for (const auto& item : destruct.items) { if (!item.defVal) { if (!isAssignable(item.target)) { -- cgit v1.2.3-55-g6feb