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)); |