From d90857cc05cd0820a2057c547e95b02d24d15412 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Tue, 26 Aug 2025 12:50:50 +0800 Subject: Added function argument destructuring. --- src/yuescript/yue_ast.h | 2 +- src/yuescript/yue_compiler.cpp | 54 +++++++++++++++++++++++++++++++++++++++--- src/yuescript/yue_parser.cpp | 2 +- 3 files changed, 53 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 1937eb8..6e1bb88 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -780,7 +780,7 @@ AST_NODE(Export) AST_END(Export) AST_NODE(FnArgDef) - ast_sel name; + ast_sel name; ast_ptr op; ast_ptr label; ast_ptr defaultValue; diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index d676750..33161a7 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -78,7 +78,7 @@ static std::unordered_set Metamethods = { "close"s // Lua 5.4 }; -const std::string_view version = "0.29.3"sv; +const std::string_view version = "0.29.4"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -1982,7 +1982,7 @@ private: return indent() + "local "s + join(defs, ", "sv); } - std::string getDestrucureDefine(ExpListAssign_t* assignment) { + std::string getDestructureDefine(ExpListAssign_t* assignment) { auto info = extractDestructureInfo(assignment, true, false); if (!info.destructures.empty()) { str_list defs; @@ -2013,8 +2013,31 @@ private: return clearBuf(); } + str_list getArgDestructureList(ExpListAssign_t* assignment) { + str_list defs; + auto info = extractDestructureInfo(assignment, true, false); + if (!info.destructures.empty()) { + for (const auto& des : info.destructures) { + if (std::holds_alternative(des)) { + const auto& destruct = std::get(des); + for (const auto& item : destruct.items) { + if (item.targetVar.empty()) { + throw CompileError("can only destruct argument to variable"sv, item.target); + } else { + defs.push_back(item.targetVar); + } + } + } else { + const auto& assignment = std::get(des); + YUEE("AST node mismatch", assignment.ptr); + } + } + } + return defs; + } + std::string getPreDefine(ExpListAssign_t* assignment) { - auto preDefine = getDestrucureDefine(assignment); + auto preDefine = getDestructureDefine(assignment); if (preDefine.empty()) { preDefine = toLocalDecl(transformAssignDefs(assignment->expList, DefOp::Mark)); } @@ -5652,6 +5675,7 @@ private: bool checkExistence = false; std::string name; std::string assignSelf; + ast_ptr assignment; }; std::list argItems; str_list temp; @@ -5706,6 +5730,22 @@ private: } break; } + case id(): { + arg.name = getUnusedName("_arg_"sv); + auto simpleValue = def->new_ptr(); + simpleValue->value.set(def->name); + auto asmt = assignmentFrom(newExp(simpleValue, def), toAst(arg.name, def), def); + arg.assignment = asmt; + break; + } + case id(): { + arg.name = getUnusedName("_arg_"sv); + auto value = def->new_ptr(); + value->item.set(def->name); + auto asmt = assignmentFrom(newExp(value, def), toAst(arg.name, def), def); + arg.assignment = asmt; + break; + } default: YUEE("AST node mismatch", def->name.get()); break; } forceAddToScope(arg.name); @@ -5724,6 +5764,14 @@ private: _buf << indent() << "end"sv << nll(def); temp.back() = clearBuf(); } + if (arg.assignment) { + auto names = getArgDestructureList(arg.assignment); + for (const auto& name : names) { + forceAddToScope(name); + } + temp.emplace_back(indent() + "local "s + join(names, ", "sv) + nll(def)); + transformAssignment(arg.assignment, temp); + } if (varNames.empty()) varNames = arg.name; else diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 1942e23..01ca083 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -893,7 +893,7 @@ YueParser::YueParser() { fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); - FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp); + FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp) | TableLit | SimpleTable; FnArgDefList = Seperator >> ( fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg >> -(space >> '`' >> space >> Name)) | -- cgit v1.2.3-55-g6feb