diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuescript/yue_ast.h | 2 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 47 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 2 |
3 files changed, 35 insertions, 16 deletions
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index b1a369b..0008fd6 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -443,7 +443,7 @@ AST_END(CompInner) | |||
| 443 | 443 | ||
| 444 | AST_NODE(Assign) | 444 | AST_NODE(Assign) |
| 445 | ast_ptr<true, Seperator_t> sep; | 445 | ast_ptr<true, Seperator_t> sep; |
| 446 | ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t> values; | 446 | ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t, SpreadListExp_t> values; |
| 447 | AST_MEMBER(Assign, &sep, &values) | 447 | AST_MEMBER(Assign, &sep, &values) |
| 448 | AST_END(Assign) | 448 | AST_END(Assign) |
| 449 | 449 | ||
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index ed0a587..8c28e61 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 78 | "close"s // Lua 5.4 | 78 | "close"s // Lua 5.4 |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | const std::string_view version = "0.29.7"sv; | 81 | const std::string_view version = "0.29.8"sv; |
| 82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
| 83 | 83 | ||
| 84 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
| @@ -2321,15 +2321,27 @@ private: | |||
| 2321 | transformAssignment(newAssignment, temp); | 2321 | transformAssignment(newAssignment, temp); |
| 2322 | varName = objVar; | 2322 | varName = objVar; |
| 2323 | } | 2323 | } |
| 2324 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 2324 | if (auto spread = ast_cast<SpreadListExp_t>(*vit)) { |
| 2325 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | 2325 | auto lenVar = getUnusedName("_len_"sv); |
| 2326 | auto assign = x->new_ptr<Assign_t>(); | 2326 | forceAddToScope(lenVar); |
| 2327 | if (vit == values.end()) { | 2327 | temp.push_back(indent() + "local "s + lenVar + " = #"s + varName + " + 1"s + nll(spread)); |
| 2328 | throw CompileError("right value missing"sv, values.front()); | 2328 | auto elmVar = getUnusedName("_elm_"sv); |
| 2329 | _buf << varName << '[' << lenVar << "],"s << lenVar << "="s << elmVar << ',' << lenVar << "+1 for "s << elmVar << " in *nil"s; | ||
| 2330 | auto stmt = toAst<Statement_t>(clearBuf(), spread); | ||
| 2331 | auto comp = stmt->appendix->item.to<CompInner_t>(); | ||
| 2332 | ast_to<CompForEach_t>(comp->items.front())->loopValue.to<StarExp_t>()->value.set(spread->exp); | ||
| 2333 | transformStatement(stmt, temp); | ||
| 2334 | } else { | ||
| 2335 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
| 2336 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | ||
| 2337 | auto assign = x->new_ptr<Assign_t>(); | ||
| 2338 | if (vit == values.end()) { | ||
| 2339 | throw CompileError("right value missing"sv, values.front()); | ||
| 2340 | } | ||
| 2341 | assign->values.push_back(*vit); | ||
| 2342 | newAssignment->action.set(assign); | ||
| 2343 | transformAssignment(newAssignment, temp); | ||
| 2329 | } | 2344 | } |
| 2330 | assign->values.push_back(*vit); | ||
| 2331 | newAssignment->action.set(assign); | ||
| 2332 | transformAssignment(newAssignment, temp); | ||
| 2333 | if (extraScoped) { | 2345 | if (extraScoped) { |
| 2334 | popScope(); | 2346 | popScope(); |
| 2335 | temp.push_back(indent() + "end"s + nlr(x)); | 2347 | temp.push_back(indent() + "end"s + nlr(x)); |
| @@ -2848,6 +2860,7 @@ private: | |||
| 2848 | case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; | 2860 | case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; |
| 2849 | case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(value), out); break; | 2861 | case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(value), out); break; |
| 2850 | case id<Exp_t>(): transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break; | 2862 | case id<Exp_t>(): transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break; |
| 2863 | case id<SpreadListExp_t>(): throw CompileError("can only be used for ranged table append assignments"sv, value); break; | ||
| 2851 | default: YUEE("AST node mismatch", value); break; | 2864 | default: YUEE("AST node mismatch", value); break; |
| 2852 | } | 2865 | } |
| 2853 | } | 2866 | } |
| @@ -8268,9 +8281,16 @@ private: | |||
| 8268 | } | 8281 | } |
| 8269 | return; | 8282 | return; |
| 8270 | } | 8283 | } |
| 8271 | auto def = ast_cast<NormalDef_t>(comp->items.front()); | 8284 | ast_node* value = nullptr; |
| 8272 | if (!def || def->defVal) { | 8285 | bool isSpread = ast_is<SpreadListExp_t>(comp->items.front()); |
| 8273 | throw CompileError("invalid comprehension expression", comp->items.front()); | 8286 | if (isSpread) { |
| 8287 | value = comp->items.front(); | ||
| 8288 | } else { | ||
| 8289 | auto def = ast_cast<NormalDef_t>(comp->items.front()); | ||
| 8290 | if (!def || def->defVal) { | ||
| 8291 | throw CompileError("invalid comprehension expression", comp->items.front()); | ||
| 8292 | } | ||
| 8293 | value = def->item.get(); | ||
| 8274 | } | 8294 | } |
| 8275 | bool extraScope = false; | 8295 | bool extraScope = false; |
| 8276 | switch (usage) { | 8296 | switch (usage) { |
| @@ -8294,7 +8314,6 @@ private: | |||
| 8294 | default: | 8314 | default: |
| 8295 | break; | 8315 | break; |
| 8296 | } | 8316 | } |
| 8297 | auto value = def->item.get(); | ||
| 8298 | auto compInner = static_cast<CompInner_t*>(comp->items.back()); | 8317 | auto compInner = static_cast<CompInner_t*>(comp->items.back()); |
| 8299 | str_list temp; | 8318 | str_list temp; |
| 8300 | std::string accumVar = getUnusedName("_accum_"sv); | 8319 | std::string accumVar = getUnusedName("_accum_"sv); |
| @@ -8318,7 +8337,7 @@ private: | |||
| 8318 | } | 8337 | } |
| 8319 | } | 8338 | } |
| 8320 | { | 8339 | { |
| 8321 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 8340 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + (isSpread ? "][]"s : "]"s), x); |
| 8322 | auto assign = x->new_ptr<Assign_t>(); | 8341 | auto assign = x->new_ptr<Assign_t>(); |
| 8323 | assign->values.push_back(value); | 8342 | assign->values.push_back(value); |
| 8324 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 8343 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 44baced..fccb6fb 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -547,7 +547,7 @@ YueParser::YueParser() { | |||
| 547 | 547 | ||
| 548 | Assign = '=' >> space >> Seperator >> ( | 548 | Assign = '=' >> space >> Seperator >> ( |
| 549 | With | If | Switch | TableBlock | | 549 | With | If | Switch | TableBlock | |
| 550 | Exp >> *(space >> set(",;") >> space >> Exp) | 550 | (SpreadListExp | Exp) >> *(space >> set(",;") >> space >> (SpreadListExp | Exp)) |
| 551 | ); | 551 | ); |
| 552 | 552 | ||
| 553 | UpdateOp = | 553 | UpdateOp = |
