From d905d9744344da7376ae56e7dc270a81da33d15f Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 7 May 2025 18:16:22 +0800 Subject: Updated. --- spec/inputs/switch.yue | 56 +++++++++- spec/outputs/switch.lua | 241 +++++++++++++++++++++++++++++++++++++++++ src/yuescript/yue_compiler.cpp | 66 ++++++----- 3 files changed, 334 insertions(+), 29 deletions(-) diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue index 49d47f3..7ff3118 100644 --- a/spec/inputs/switch.yue +++ b/spec/inputs/switch.yue @@ -165,5 +165,59 @@ do print item when [a = 1, b = "abc"] print a, b -nil +do + switch tb + when [1, 2, 3] + print "1, 2, 3" + when [1, b, 3] + print "1, #{b}, 3" + when [1, 2, b = 3] + print "1, 2, #{b}" + +do + switch tb + when success: true, :result + print "success", result + when success: false + print "failed", result + else + print "invalid" + +do + switch tb + when {type: "success", :content} + print "success", content + when {type: "error", :content} + print "failed", content + else + print "invalid" + +do + switch tb + when [ + {a: 1, b: 2} + {a: 3, b: 4} + {a: 5, b: 6} + fourth + ] + print "matched", fourth + + switch tb + when [ + {c: 1, d: 2} + {c: 3, d: 4} + {c: 5, d: 6} + ] + print "OK" + when [ + _ + _ + {a: 1, b: 2} + {a: 3, b: 4} + {a: 5, b: 6} + sixth + ] + print "matched", sixth + +nil \ No newline at end of file diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua index e4dedc9..0f8bba2 100644 --- a/spec/outputs/switch.lua +++ b/spec/outputs/switch.lua @@ -415,4 +415,245 @@ do end end end +do + local _exp_0 = tb + local _type_0 = type(_exp_0) + local _tab_0 = "table" == _type_0 or "userdata" == _type_0 + local _match_0 = false + if _tab_0 then + if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then + _match_0 = true + print("1, 2, 3") + end + end + if not _match_0 then + local _match_1 = false + if _tab_0 then + local b = _exp_0[2] + if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then + _match_1 = true + print("1, " .. tostring(b) .. ", 3") + end + end + if not _match_1 then + if _tab_0 then + local b = _exp_0[3] + if b == nil then + b = 3 + end + if 1 == _exp_0[1] and 2 == _exp_0[2] then + print("1, 2, " .. tostring(b)) + end + end + end + end +end +do + local _exp_0 = tb + local _type_0 = type(_exp_0) + local _tab_0 = "table" == _type_0 or "userdata" == _type_0 + local _match_0 = false + if _tab_0 then + local result = _exp_0.result + if true == _exp_0.success and result ~= nil then + _match_0 = true + print("success", result) + end + end + if not _match_0 then + local _match_1 = false + if _tab_0 then + if false == _exp_0.success then + _match_1 = true + print("failed", result) + end + end + if not _match_1 then + print("invalid") + end + end +end +do + local _exp_0 = tb + local _type_0 = type(_exp_0) + local _tab_0 = "table" == _type_0 or "userdata" == _type_0 + local _match_0 = false + if _tab_0 then + local content = _exp_0.content + if "success" == _exp_0.type and content ~= nil then + _match_0 = true + print("success", content) + end + end + if not _match_0 then + local _match_1 = false + if _tab_0 then + local content = _exp_0.content + if "error" == _exp_0.type and content ~= nil then + _match_1 = true + print("failed", content) + end + end + if not _match_1 then + print("invalid") + end + end +end +do + do + local _exp_0 = tb + local _type_0 = type(_exp_0) + local _tab_0 = "table" == _type_0 or "userdata" == _type_0 + if _tab_0 then + local fourth = _exp_0[4] + local _val_0 + do + local _obj_0 = _exp_0[1] + if _obj_0 ~= nil then + _val_0 = _obj_0.a + end + end + local _val_1 + do + local _obj_0 = _exp_0[1] + if _obj_0 ~= nil then + _val_1 = _obj_0.b + end + end + local _val_2 + do + local _obj_0 = _exp_0[2] + if _obj_0 ~= nil then + _val_2 = _obj_0.a + end + end + local _val_3 + do + local _obj_0 = _exp_0[2] + if _obj_0 ~= nil then + _val_3 = _obj_0.b + end + end + local _val_4 + do + local _obj_0 = _exp_0[3] + if _obj_0 ~= nil then + _val_4 = _obj_0.a + end + end + local _val_5 + do + local _obj_0 = _exp_0[3] + if _obj_0 ~= nil then + _val_5 = _obj_0.b + end + end + if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then + print("matched", fourth) + end + end + end + local _exp_0 = tb + local _type_0 = type(_exp_0) + local _tab_0 = "table" == _type_0 or "userdata" == _type_0 + local _match_0 = false + if _tab_0 then + local _val_0 + do + local _obj_0 = _exp_0[1] + if _obj_0 ~= nil then + _val_0 = _obj_0.c + end + end + local _val_1 + do + local _obj_0 = _exp_0[1] + if _obj_0 ~= nil then + _val_1 = _obj_0.d + end + end + local _val_2 + do + local _obj_0 = _exp_0[2] + if _obj_0 ~= nil then + _val_2 = _obj_0.c + end + end + local _val_3 + do + local _obj_0 = _exp_0[2] + if _obj_0 ~= nil then + _val_3 = _obj_0.d + end + end + local _val_4 + do + local _obj_0 = _exp_0[3] + if _obj_0 ~= nil then + _val_4 = _obj_0.c + end + end + local _val_5 + do + local _obj_0 = _exp_0[3] + if _obj_0 ~= nil then + _val_5 = _obj_0.d + end + end + if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 then + _match_0 = true + print("OK") + end + end + if not _match_0 then + if _tab_0 then + local sixth = _exp_0[6] + local _val_0 + do + local _obj_0 = _exp_0[3] + if _obj_0 ~= nil then + _val_0 = _obj_0.a + end + end + local _val_1 + do + local _obj_0 = _exp_0[3] + if _obj_0 ~= nil then + _val_1 = _obj_0.b + end + end + local _val_2 + do + local _obj_0 = _exp_0[4] + if _obj_0 ~= nil then + _val_2 = _obj_0.a + end + end + local _val_3 + do + local _obj_0 = _exp_0[4] + if _obj_0 ~= nil then + _val_3 = _obj_0.b + end + end + local _val_4 + do + local _obj_0 = _exp_0[5] + if _obj_0 ~= nil then + _val_4 = _obj_0.a + end + end + local _val_5 + do + local _obj_0 = _exp_0[5] + if _obj_0 ~= nil then + _val_5 = _obj_0.b + end + end + if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and sixth ~= nil then + print("matched", sixth) + end + end + end +end return nil diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 06f0d6d..bc4574b 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -2814,19 +2814,19 @@ private: if (!varDefOnly) throw e; } if (!assignable && !varDefOnly) { - if (optional) { - if (defVal) { - throw CompileError("default value is not supported here"sv, defVal); - } - auto exp = static_cast(pair); - auto chain = exp->new_ptr(); - auto indexItem = toAst(std::to_string(index), exp); - chain->items.push_back(indexItem); - pairs.push_back({exp, Empty, chain, nullptr}); - break; - } else { - throw CompileError("can't destructure value"sv, pair); + if (optional) break; + throw CompileError("can't destructure value"sv, pair); + } + if (optional && varDefOnly && !assignable) { + if (defVal) { + throw CompileError("default value is not supported here"sv, defVal); } + auto exp = static_cast(pair); + auto chain = exp->new_ptr(); + auto indexItem = toAst(std::to_string(index), exp); + chain->items.push_back(indexItem); + pairs.push_back({exp, Empty, chain, nullptr}); + break; } auto value = singleValueFrom(pair); auto item = value->item.get(); @@ -2914,17 +2914,17 @@ private: if (!varDefOnly) throw e; } if (!assignable && !varDefOnly) { - if (optional) { - if (defVal) { - throw CompileError("default value is not supported here"sv, defVal); - } - auto chain = exp->new_ptr(); - if (keyIndex) chain->items.push_back(keyIndex); - pairs.push_back({exp, Empty, chain, nullptr}); - break; - } else { - throw CompileError("can't destructure value"sv, exp); + if (optional) break; + throw CompileError("can't destructure value"sv, pair); + } + if (optional && varDefOnly && !assignable) { + if (defVal) { + throw CompileError("default value is not supported here"sv, defVal); } + auto chain = exp->new_ptr(); + if (keyIndex) chain->items.push_back(keyIndex); + pairs.push_back({exp, Empty, chain, nullptr}); + break; } auto item = singleValueFrom(exp)->item.get(); ast_node* subExp = ast_cast(item); @@ -10652,16 +10652,26 @@ private: for (const auto& item : destruct.items) { if (!item.defVal) { if (!isAssignable(item.target)) { - transformExp(item.target, conds, ExpUsage::Closure); auto callable = chainValue->items.front(); auto chain = callable->new_ptr(); chain->items.push_back(callable); chain->items.dup(item.structure->items); - transformChainValue(chain, conds, ExpUsage::Closure); - auto vStr = conds.back(); - conds.pop_back(); - conds.back().append(" == "s); - conds.back().append(vStr); + if (specialChainValue(chain) == ChainType::Common) { + transformChainValue(chain, conds, ExpUsage::Closure); + auto vStr = conds.back(); + conds.pop_back(); + transformExp(item.target, conds, ExpUsage::Closure); + conds.back().append(" == "s); + conds.back().append(vStr); + } else { + auto varName = getUnusedName("_val_"sv); + auto vExp = toAst(varName, chain); + auto asmt = assignmentFrom(vExp, newExp(chain, chain), chain); + transformAssignment(asmt, temp); + transformExp(item.target, conds, ExpUsage::Closure); + conds.back().append(" == "s); + conds.back().append(varName); + } } else { transformExp(item.target, conds, ExpUsage::Closure); conds.back().append(" ~= nil"s); -- cgit v1.2.3-55-g6feb