diff options
| author | Li Jin <dragon-fly@qq.com> | 2025-05-23 12:22:21 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2025-05-23 12:22:21 +0800 |
| commit | cf0a0f37bf07eb8e9435febe96e3adfe45004f91 (patch) | |
| tree | 480cb978564d77ac088a505704e7df34863e8cb7 /src | |
| parent | 7bf2832d653027932fd845ba1462dd385ac32ab8 (diff) | |
| download | yuescript-cf0a0f37bf07eb8e9435febe96e3adfe45004f91.tar.gz yuescript-cf0a0f37bf07eb8e9435febe96e3adfe45004f91.tar.bz2 yuescript-cf0a0f37bf07eb8e9435febe96e3adfe45004f91.zip | |
Added break with value to with syntax.
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 132 |
1 files changed, 103 insertions, 29 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 60ed7ac..7abc929 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.28.2"sv; | 81 | const std::string_view version = "0.28.3"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 { |
| @@ -2064,6 +2064,9 @@ private: | |||
| 2064 | } | 2064 | } |
| 2065 | 2065 | ||
| 2066 | bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | 2066 | bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { |
| 2067 | if (assignment->action.is<SubBackcall_t>()) { | ||
| 2068 | YUEE("AST node mismatch", assignment->action); | ||
| 2069 | } | ||
| 2067 | checkAssignable(assignment->expList); | 2070 | checkAssignable(assignment->expList); |
| 2068 | BLOCK_START | 2071 | BLOCK_START |
| 2069 | auto assign = ast_cast<Assign_t>(assignment->action); | 2072 | auto assign = ast_cast<Assign_t>(assignment->action); |
| @@ -8195,18 +8198,18 @@ private: | |||
| 8195 | transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); | 8198 | transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); |
| 8196 | } | 8199 | } |
| 8197 | 8200 | ||
| 8198 | void transform_plain_body(ast_node* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8201 | void transform_plain_body(ast_node* bodyOrStmt, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 8199 | switch (body->get_id()) { | 8202 | switch (bodyOrStmt->get_id()) { |
| 8200 | case id<Block_t>(): | 8203 | case id<Block_t>(): |
| 8201 | transformBlock(static_cast<Block_t*>(body), out, usage, assignList); | 8204 | transformBlock(static_cast<Block_t*>(bodyOrStmt), out, usage, assignList); |
| 8202 | break; | 8205 | break; |
| 8203 | case id<Statement_t>(): { | 8206 | case id<Statement_t>(): { |
| 8204 | auto newBlock = body->new_ptr<Block_t>(); | 8207 | auto newBlock = bodyOrStmt->new_ptr<Block_t>(); |
| 8205 | newBlock->statements.push_back(body); | 8208 | newBlock->statements.push_back(bodyOrStmt); |
| 8206 | transformBlock(newBlock, out, usage, assignList); | 8209 | transformBlock(newBlock, out, usage, assignList); |
| 8207 | break; | 8210 | break; |
| 8208 | } | 8211 | } |
| 8209 | default: YUEE("AST node mismatch", body); break; | 8212 | default: YUEE("AST node mismatch", bodyOrStmt); break; |
| 8210 | } | 8213 | } |
| 8211 | } | 8214 | } |
| 8212 | 8215 | ||
| @@ -8477,12 +8480,17 @@ private: | |||
| 8477 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); | 8480 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); |
| 8478 | auto& lenAssign = out.emplace_back(clearBuf()); | 8481 | auto& lenAssign = out.emplace_back(clearBuf()); |
| 8479 | transformForHead(forNode, out); | 8482 | transformForHead(forNode, out); |
| 8480 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 8483 | if (hasBreakWithValue(breakLoopType)) { |
| 8481 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forNode->body); | ||
| 8482 | expList->followStmt = followStmt.get(); | ||
| 8483 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
| 8484 | if (!expList->followStmtProcessed) { | ||
| 8485 | lenAssign.clear(); | 8484 | lenAssign.clear(); |
| 8485 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Common); | ||
| 8486 | } else { | ||
| 8487 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | ||
| 8488 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forNode->body); | ||
| 8489 | expList->followStmt = followStmt.get(); | ||
| 8490 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
| 8491 | if (!expList->followStmtProcessed) { | ||
| 8492 | lenAssign.clear(); | ||
| 8493 | } | ||
| 8486 | } | 8494 | } |
| 8487 | popScope(); | 8495 | popScope(); |
| 8488 | out.push_back(indent() + "end"s + nlr(forNode)); | 8496 | out.push_back(indent() + "end"s + nlr(forNode)); |
| @@ -8584,12 +8592,17 @@ private: | |||
| 8584 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); | 8592 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); |
| 8585 | auto& lenAssign = out.emplace_back(clearBuf()); | 8593 | auto& lenAssign = out.emplace_back(clearBuf()); |
| 8586 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); | 8594 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); |
| 8587 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 8595 | if (hasBreakWithValue(breakLoopType)) { |
| 8588 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forEach->body); | ||
| 8589 | expList->followStmt = followStmt.get(); | ||
| 8590 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
| 8591 | if (!expList->followStmtProcessed) { | ||
| 8592 | lenAssign.clear(); | 8596 | lenAssign.clear(); |
| 8597 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Common); | ||
| 8598 | } else { | ||
| 8599 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | ||
| 8600 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forEach->body); | ||
| 8601 | expList->followStmt = followStmt.get(); | ||
| 8602 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
| 8603 | if (!expList->followStmtProcessed) { | ||
| 8604 | lenAssign.clear(); | ||
| 8605 | } | ||
| 8593 | } | 8606 | } |
| 8594 | popScope(); | 8607 | popScope(); |
| 8595 | out.push_back(indent() + "end"s + nlr(forEach)); | 8608 | out.push_back(indent() + "end"s + nlr(forEach)); |
| @@ -9476,15 +9489,66 @@ private: | |||
| 9476 | } | 9489 | } |
| 9477 | } | 9490 | } |
| 9478 | _withVars.push(withVar); | 9491 | _withVars.push(withVar); |
| 9492 | std::string breakWithVar; | ||
| 9493 | if (assignList || returnValue) { | ||
| 9494 | auto breakLoopType = getBreakLoopType(with->body, withVar); | ||
| 9495 | if (hasBreakWithValue(breakLoopType)) { | ||
| 9496 | breakWithVar = withVar; | ||
| 9497 | } | ||
| 9498 | } | ||
| 9479 | if (with->eop) { | 9499 | if (with->eop) { |
| 9480 | auto ifNode = x->new_ptr<If_t>(); | 9500 | auto ifNode = x->new_ptr<If_t>(); |
| 9481 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); | 9501 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); |
| 9482 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); | 9502 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); |
| 9483 | ifNode->nodes.push_back(with->body); | 9503 | ifNode->nodes.push_back(with->body); |
| 9484 | transformIf(ifNode, temp, ExpUsage::Common); | 9504 | if (breakWithVar.empty()) { |
| 9505 | transformIf(ifNode, temp, ExpUsage::Common); | ||
| 9506 | } else { | ||
| 9507 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 9508 | simpleValue->value.set(ifNode); | ||
| 9509 | auto exp = newExp(simpleValue, x); | ||
| 9510 | auto expList = x->new_ptr<ExpList_t>(); | ||
| 9511 | expList->exprs.push_back(exp); | ||
| 9512 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
| 9513 | expListAssign->expList.set(expList); | ||
| 9514 | auto stmt = x->new_ptr<Statement_t>(); | ||
| 9515 | stmt->content.set(expListAssign); | ||
| 9516 | auto whileNode = toAst<While_t>("while true do break"s, x); | ||
| 9517 | auto block = x->new_ptr<Block_t>(); | ||
| 9518 | block->statements.push_back(stmt); | ||
| 9519 | block->statements.push_back(whileNode->body); | ||
| 9520 | auto body = x->new_ptr<Body_t>(); | ||
| 9521 | body->content.set(block); | ||
| 9522 | whileNode->body.set(block); | ||
| 9523 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
| 9524 | sVal->value.set(whileNode); | ||
| 9525 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | ||
| 9526 | transformAssignment(asmt, temp); | ||
| 9527 | } | ||
| 9485 | } else { | 9528 | } else { |
| 9486 | bool transformed = false; | 9529 | bool transformed = false; |
| 9487 | if (!extraScope && assignList) { | 9530 | if (!breakWithVar.empty()) { |
| 9531 | auto whileNode = toAst<While_t>("while true do break"s, x); | ||
| 9532 | auto block = x->new_ptr<Block_t>(); | ||
| 9533 | if (auto blk = with->body.as<Block_t>()) { | ||
| 9534 | block->statements.dup(blk->statements); | ||
| 9535 | } else { | ||
| 9536 | auto stmt = with->body.to<Statement_t>(); | ||
| 9537 | block->statements.push_back(stmt); | ||
| 9538 | } | ||
| 9539 | auto breakLoop = whileNode->body.to<Statement_t>()->content.as<BreakLoop_t>(); | ||
| 9540 | if (!(breakLoop && breakLoop->type.is<Break_t>())) { | ||
| 9541 | block->statements.push_back(whileNode->body); | ||
| 9542 | } | ||
| 9543 | auto body = x->new_ptr<Body_t>(); | ||
| 9544 | body->content.set(block); | ||
| 9545 | whileNode->body.set(block); | ||
| 9546 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
| 9547 | sVal->value.set(whileNode); | ||
| 9548 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | ||
| 9549 | transformAssignment(asmt, temp); | ||
| 9550 | transformed = true; | ||
| 9551 | } else if (!extraScope && assignList) { | ||
| 9488 | if (auto block = with->body.as<Block_t>()) { | 9552 | if (auto block = with->body.as<Block_t>()) { |
| 9489 | if (!block->statements.empty()) { | 9553 | if (!block->statements.empty()) { |
| 9490 | Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); | 9554 | Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); |
| @@ -10543,12 +10607,17 @@ private: | |||
| 10543 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 10607 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
| 10544 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 10608 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); |
| 10545 | pushScope(); | 10609 | pushScope(); |
| 10546 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 10610 | if (hasBreakWithValue(breakLoopType)) { |
| 10547 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
| 10548 | assignLeft->followStmt = followStmt.get(); | ||
| 10549 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 10550 | if (!assignLeft->followStmtProcessed) { | ||
| 10551 | lenAssign.clear(); | 10611 | lenAssign.clear(); |
| 10612 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 10613 | } else { | ||
| 10614 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 10615 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
| 10616 | assignLeft->followStmt = followStmt.get(); | ||
| 10617 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 10618 | if (!assignLeft->followStmtProcessed) { | ||
| 10619 | lenAssign.clear(); | ||
| 10620 | } | ||
| 10552 | } | 10621 | } |
| 10553 | popScope(); | 10622 | popScope(); |
| 10554 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 10623 | temp.push_back(indent() + "end"s + nlr(whileNode)); |
| @@ -10593,12 +10662,17 @@ private: | |||
| 10593 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 10662 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
| 10594 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 10663 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); |
| 10595 | pushScope(); | 10664 | pushScope(); |
| 10596 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 10665 | if (hasBreakWithValue(breakLoopType)) { |
| 10597 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
| 10598 | assignLeft->followStmt = followStmt.get(); | ||
| 10599 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 10600 | if (!assignLeft->followStmtProcessed) { | ||
| 10601 | lenAssign.clear(); | 10666 | lenAssign.clear(); |
| 10667 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 10668 | } else { | ||
| 10669 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 10670 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
| 10671 | assignLeft->followStmt = followStmt.get(); | ||
| 10672 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 10673 | if (!assignLeft->followStmtProcessed) { | ||
| 10674 | lenAssign.clear(); | ||
| 10675 | } | ||
| 10602 | } | 10676 | } |
| 10603 | popScope(); | 10677 | popScope(); |
| 10604 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 10678 | temp.push_back(indent() + "end"s + nlr(whileNode)); |
