aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuescript/yue_compiler.cpp132
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
81const std::string_view version = "0.28.2"sv; 81const std::string_view version = "0.28.3"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class 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));