aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2024-09-04 12:16:10 +0800
committerLi Jin <dragon-fly@qq.com>2024-09-04 12:16:25 +0800
commit461bf7c32408553125d71b23e04e21fed690c4f5 (patch)
tree4442efd0fc2524e82be63e12e3e046a0532b26dd /src
parent2f8215df7288e0aac690c8e8b1ff79865f114302 (diff)
downloadyuescript-461bf7c32408553125d71b23e04e21fed690c4f5.tar.gz
yuescript-461bf7c32408553125d71b23e04e21fed690c4f5.tar.bz2
yuescript-461bf7c32408553125d71b23e04e21fed690c4f5.zip
fix more cases for evaluation order of multi-value assignments.v0.25.1
Diffstat (limited to 'src')
-rw-r--r--src/yuescript/yue_compiler.cpp121
1 files changed, 74 insertions, 47 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index cbb5f81..5d031db 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
75 "close"s // Lua 5.4 75 "close"s // Lua 5.4
76}; 76};
77 77
78const std::string_view version = "0.25.0"sv; 78const std::string_view version = "0.25.1"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class CompileError : public std::logic_error {
@@ -2047,34 +2047,34 @@ private:
2047 } 2047 }
2048 throw CompileError(clearBuf(), values.front()); 2048 throw CompileError(clearBuf(), values.front());
2049 } 2049 }
2050 bool checkValuesLater = false;
2051 if (exprs.size() > values.size()) { 2050 if (exprs.size() > values.size()) {
2052 BLOCK_START 2051 BLOCK_START
2052 bool needHoldValues = false;
2053 switch (values.back()->get_id()) { 2053 switch (values.back()->get_id()) {
2054 case id<If_t>(): 2054 case id<If_t>():
2055 case id<Switch_t>(): 2055 case id<Switch_t>():
2056 checkValuesLater = true; 2056 needHoldValues = true;
2057 break; 2057 break;
2058 } 2058 }
2059 BREAK_IF(checkValuesLater); 2059 if (!needHoldValues) {
2060 auto value = singleValueFrom(values.back()); 2060 if (auto value = singleValueFrom(values.back())) {
2061 if (!value) { 2061 if (auto val = value->item.as<SimpleValue_t>()) {
2062 _buf << exprs.size() << " right values expected, got "sv << values.size(); 2062 switch (val->value->get_id()) {
2063 throw CompileError(clearBuf(), values.front()); 2063 case id<If_t>():
2064 } 2064 case id<Switch_t>():
2065 if (auto val = value->item.as<SimpleValue_t>()) { 2065 case id<Do_t>():
2066 switch (val->value->get_id()) { 2066 case id<Try_t>():
2067 case id<If_t>(): 2067 needHoldValues = true;
2068 case id<Switch_t>(): 2068 break;
2069 case id<Do_t>(): 2069 }
2070 case id<Try_t>(): 2070 } else if (auto chainValue = value->item.as<ChainValue_t>()) {
2071 checkValuesLater = true; 2071 if (chainValue && ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) {
2072 break; 2072 needHoldValues = true;
2073 }
2074 }
2073 } 2075 }
2074 BREAK_IF(checkValuesLater);
2075 } 2076 }
2076 auto chainValue = value->item.as<ChainValue_t>(); 2077 if (!needHoldValues) {
2077 if (!chainValue || !ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) {
2078 _buf << exprs.size() << " right values expected, got "sv << values.size(); 2078 _buf << exprs.size() << " right values expected, got "sv << values.size();
2079 throw CompileError(clearBuf(), values.front()); 2079 throw CompileError(clearBuf(), values.front());
2080 } 2080 }
@@ -2138,7 +2138,7 @@ private:
2138 temp.push_back(indent() + "do"s + nll(assignment)); 2138 temp.push_back(indent() + "do"s + nll(assignment));
2139 pushScope(); 2139 pushScope();
2140 } 2140 }
2141 transformAssignmentCommon(preAssignment, temp); 2141 transformAssignment(preAssignment, temp);
2142 transformAssignment(assignment, temp); 2142 transformAssignment(assignment, temp);
2143 if (needScope) { 2143 if (needScope) {
2144 popScope(); 2144 popScope();
@@ -2148,17 +2148,52 @@ private:
2148 return; 2148 return;
2149 BLOCK_END 2149 BLOCK_END
2150 } 2150 }
2151 if (!checkValuesLater) { 2151 {
2152 auto vit = values.begin(); 2152 auto vit = values.begin();
2153 for (auto it = exprs.begin(); it != exprs.end(); ++it) { 2153 for (auto it = exprs.begin(); it != exprs.end(); ++it) {
2154 auto splitAssignment = [&]() {
2155 auto beforeAssignment = x->new_ptr<ExpListAssign_t>();
2156 auto afterAssignment = x->new_ptr<ExpListAssign_t>();
2157 {
2158 auto beforeExpList = x->new_ptr<ExpList_t>();
2159 auto beforeAssign = x->new_ptr<Assign_t>();
2160 beforeAssignment->expList.set(beforeExpList);
2161 beforeAssignment->action.set(beforeAssign);
2162 auto afterExpList = x->new_ptr<ExpList_t>();
2163 auto afterAssign = x->new_ptr<Assign_t>();
2164 afterAssignment->expList.set(afterExpList);
2165 afterAssignment->action.set(afterAssign);
2166 ExpList_t* currentExpList = beforeExpList.get();
2167 for (auto exp : exprs) {
2168 if (exp != *it) {
2169 currentExpList->exprs.push_back(exp);
2170 } else {
2171 currentExpList = afterExpList.get();
2172 }
2173 }
2174 Assign_t* currentAssign = beforeAssign.get();
2175 for (auto value : values) {
2176 if (value != *vit) {
2177 currentAssign->values.push_back(value);
2178 } else {
2179 currentAssign = afterAssign.get();
2180 }
2181 }
2182 }
2183 return std::make_pair(beforeAssignment, afterAssignment);
2184 };
2154 BLOCK_START 2185 BLOCK_START
2155 auto value = singleValueFrom(*it); 2186 auto value = singleValueFrom(*it);
2156 BREAK_IF(!value); 2187 BREAK_IF(!value);
2157 auto chainValue = value->item.as<ChainValue_t>(); 2188 auto chainValue = value->item.as<ChainValue_t>();
2158 BREAK_IF(!chainValue); 2189 BREAK_IF(!chainValue);
2159 str_list temp;
2160 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { 2190 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) {
2161 BREAK_IF(!dot->name.is<Metatable_t>()); 2191 BREAK_IF(!dot->name.is<Metatable_t>());
2192 str_list temp;
2193 auto [beforeAssignment, afterAssignment] = splitAssignment();
2194 if (!beforeAssignment->expList->exprs.empty()) {
2195 transformAssignment(beforeAssignment, temp);
2196 }
2162 str_list args; 2197 str_list args;
2163 auto tmpChain = chainValue->new_ptr<ChainValue_t>(); 2198 auto tmpChain = chainValue->new_ptr<ChainValue_t>();
2164 tmpChain->items.dup(chainValue->items); 2199 tmpChain->items.dup(chainValue->items);
@@ -2178,7 +2213,17 @@ private:
2178 transformAssignItem(*vit, args); 2213 transformAssignItem(*vit, args);
2179 _buf << indent() << globalVar("setmetatable"sv, x, AccessType::Read) << '(' << join(args, ", "sv) << ')' << nll(x); 2214 _buf << indent() << globalVar("setmetatable"sv, x, AccessType::Read) << '(' << join(args, ", "sv) << ')' << nll(x);
2180 temp.push_back(clearBuf()); 2215 temp.push_back(clearBuf());
2216 if (!afterAssignment->expList->exprs.empty()) {
2217 transformAssignment(afterAssignment, temp);
2218 }
2219 out.push_back(join(temp));
2220 return;
2181 } else if (ast_is<TableAppendingOp_t>(chainValue->items.back())) { 2221 } else if (ast_is<TableAppendingOp_t>(chainValue->items.back())) {
2222 str_list temp;
2223 auto [beforeAssignment, afterAssignment] = splitAssignment();
2224 if (!beforeAssignment->expList->exprs.empty()) {
2225 transformAssignment(beforeAssignment, temp);
2226 }
2182 auto tmpChain = chainValue->new_ptr<ChainValue_t>(); 2227 auto tmpChain = chainValue->new_ptr<ChainValue_t>();
2183 tmpChain->items.dup(chainValue->items); 2228 tmpChain->items.dup(chainValue->items);
2184 tmpChain->items.pop_back(); 2229 tmpChain->items.pop_back();
@@ -2220,32 +2265,14 @@ private:
2220 popScope(); 2265 popScope();
2221 temp.push_back(indent() + "end"s + nlr(x)); 2266 temp.push_back(indent() + "end"s + nlr(x));
2222 } 2267 }
2223 } else 2268 if (!afterAssignment->expList->exprs.empty()) {
2224 break; 2269 transformAssignment(afterAssignment, temp);
2225 auto newExpList = x->new_ptr<ExpList_t>(); 2270 }
2226 auto newAssign = x->new_ptr<Assign_t>();
2227 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2228 newAssignment->expList.set(newExpList);
2229 newAssignment->action.set(newAssign);
2230 for (auto exp : exprs) {
2231 if (exp != *it) newExpList->exprs.push_back(exp);
2232 }
2233 for (auto value : values) {
2234 if (value != *vit) newAssign->values.push_back(value);
2235 }
2236 if (newExpList->exprs.empty() && newAssign->values.empty()) {
2237 out.push_back(join(temp)); 2271 out.push_back(join(temp));
2238 return; 2272 return;
2273 } else {
2274 break;
2239 } 2275 }
2240 if (newExpList->exprs.size() < newAssign->values.size()) {
2241 auto exp = toAst<Exp_t>("_"sv, x);
2242 while (newExpList->exprs.size() < newAssign->values.size()) {
2243 newExpList->exprs.push_back(exp);
2244 }
2245 }
2246 transformAssignment(newAssignment, temp);
2247 out.push_back(join(temp));
2248 return;
2249 BLOCK_END 2276 BLOCK_END
2250 if (vit != values.end()) ++vit; 2277 if (vit != values.end()) ++vit;
2251 } 2278 }
@@ -2432,7 +2459,7 @@ private:
2432 if (!assignment.extraAssignment) { 2459 if (!assignment.extraAssignment) {
2433 auto names = transformAssignDefs(assignment.ptr->expList, DefOp::Get); 2460 auto names = transformAssignDefs(assignment.ptr->expList, DefOp::Get);
2434 for (const auto& name : names) { 2461 for (const auto& name : names) {
2435 if (addToScope(name.first)) { 2462 if (!isDefined(name.first)) {
2436 defs.push_back(name.first); 2463 defs.push_back(name.first);
2437 } 2464 }
2438 } 2465 }