diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 121 |
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 | ||
| 78 | const std::string_view version = "0.25.0"sv; | 78 | const std::string_view version = "0.25.1"sv; |
| 79 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; |
| 80 | 80 | ||
| 81 | class CompileError : public std::logic_error { | 81 | class 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 | } |
