@@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = {
7878 " close" s // Lua 5.4
7979};
8080
81- const std::string_view version = " 0.28.4 " sv;
81+ const std::string_view version = " 0.28.5 " sv;
8282const std::string_view extension = " yue" sv;
8383
8484class CompileError : public std ::logic_error {
@@ -1846,6 +1846,7 @@ class YueCompilerImpl {
18461846 case id<ForEach_t>(): transformForEach (static_cast <ForEach_t*>(value), out); break ;
18471847 case id<For_t>(): transformFor (static_cast <For_t*>(value), out); break ;
18481848 case id<While_t>(): transformWhile (static_cast <While_t*>(value), out); break ;
1849+ case id<Repeat_t>(): transformRepeat (static_cast <Repeat_t*>(value), out); break ;
18491850 case id<Do_t>(): transformDo (static_cast <Do_t*>(value), out, ExpUsage::Common); break ;
18501851 case id<Try_t>(): transformTry (static_cast <Try_t*>(value), out, ExpUsage::Common); break ;
18511852 case id<Comprehension_t>(): {
@@ -2400,6 +2401,13 @@ class YueCompilerImpl {
24002401 out.back ().insert (0 , preDefine);
24012402 return false ;
24022403 }
2404+ case id<Repeat_t>(): {
2405+ auto expList = assignment->expList .get ();
2406+ std::string preDefine = getPreDefineLine (assignment);
2407+ transformRepeatInPlace (static_cast <Repeat_t*>(value), out, expList);
2408+ out.back ().insert (0 , preDefine);
2409+ return false ;
2410+ }
24032411 case id<TableLit_t>(): {
24042412 auto tableLit = static_cast <TableLit_t*>(value);
24052413 if (hasSpreadExp (tableLit->values .objects ())) {
@@ -4471,6 +4479,7 @@ class YueCompilerImpl {
44714479 case id<ForEach_t>(): transformForEachClosure (static_cast <ForEach_t*>(value), out); break ;
44724480 case id<For_t>(): transformForClosure (static_cast <For_t*>(value), out); break ;
44734481 case id<While_t>(): transformWhileClosure (static_cast <While_t*>(value), out); break ;
4482+ case id<Repeat_t>(): transformRepeatClosure (static_cast <Repeat_t*>(value), out); break ;
44744483 case id<Do_t>(): transformDo (static_cast <Do_t*>(value), out, ExpUsage::Closure); break ;
44754484 case id<Try_t>(): transformTry (static_cast <Try_t*>(value), out, ExpUsage::Closure); break ;
44764485 case id<UnaryValue_t>(): transformUnaryValue (static_cast <UnaryValue_t*>(value), out); break ;
@@ -5445,6 +5454,9 @@ class YueCompilerImpl {
54455454 case id<While_t>():
54465455 transformWhileInPlace (static_cast <While_t*>(value), out);
54475456 return ;
5457+ case id<Repeat_t>():
5458+ transformRepeatInPlace (static_cast <Repeat_t*>(value), out);
5459+ return ;
54485460 case id<For_t>():
54495461 transformForInPlace (static_cast <For_t*>(value), out);
54505462 return ;
@@ -8386,7 +8398,7 @@ class YueCompilerImpl {
83868398 std::string transformRepeatBody (Repeat_t* repeatNode, str_list& out) {
83878399 str_list temp;
83888400 bool extraDo = false ;
8389- auto body = repeatNode->body -> content .get ();
8401+ auto body = repeatNode->body .get ();
83908402 auto breakLoopType = getBreakLoopType (body, Empty);
83918403 bool withContinue = hasContinue (breakLoopType);
83928404 std::string conditionVar;
@@ -9513,38 +9525,29 @@ class YueCompilerImpl {
95139525 expListAssign->expList .set (expList);
95149526 auto stmt = x->new_ptr <Statement_t>();
95159527 stmt->content .set (expListAssign);
9516- auto whileNode = toAst<While_t >(" while true do break " s, x);
9528+ auto repeatNode = toAst<Repeat_t >(" repeat \n\t -- \n until true" s, x);
95179529 auto block = x->new_ptr <Block_t>();
95189530 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);
9531+ repeatNode->body .set (block);
95239532 auto sVal = x->new_ptr <SimpleValue_t>();
9524- sVal ->value .set (whileNode );
9533+ sVal ->value .set (repeatNode );
95259534 auto asmt = assignmentFrom (toAst<Exp_t>(breakWithVar, x), newExp (sVal , x), x);
95269535 transformAssignment (asmt, temp);
95279536 }
95289537 } else {
95299538 bool transformed = false ;
95309539 if (!breakWithVar.empty ()) {
9531- auto whileNode = toAst<While_t >(" while true do break " s, x);
9540+ auto repeatNode = toAst<Repeat_t >(" repeat \n\t -- \n until true" s, x);
95329541 auto block = x->new_ptr <Block_t>();
95339542 if (auto blk = with->body .as <Block_t>()) {
95349543 block->statements .dup (blk->statements );
95359544 } else {
95369545 auto stmt = with->body .to <Statement_t>();
95379546 block->statements .push_back (stmt);
95389547 }
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);
9548+ repeatNode->body .set (block);
95469549 auto sVal = x->new_ptr <SimpleValue_t>();
9547- sVal ->value .set (whileNode );
9550+ sVal ->value .set (repeatNode );
95489551 auto asmt = assignmentFrom (toAst<Exp_t>(breakWithVar, x), newExp (sVal , x), x);
95499552 transformAssignment (asmt, temp);
95509553 transformed = true ;
@@ -10708,9 +10711,7 @@ class YueCompilerImpl {
1070810711 expListAssign->expList .set (expList);
1070910712 auto stmt = x->new_ptr <Statement_t>();
1071010713 stmt->content .set (expListAssign);
10711- auto body = x->new_ptr <Body_t>();
10712- body->content .set (stmt);
10713- repeat->body .set (body);
10714+ repeat->body .set (stmt);
1071410715 transformRepeat (repeat, out);
1071510716 return ;
1071610717 }
@@ -10727,6 +10728,106 @@ class YueCompilerImpl {
1072710728 out.push_back (clearBuf ());
1072810729 }
1072910730
10731+ void transformRepeatInPlace (Repeat_t* repeatNode, str_list& out, ExpList_t* expList = nullptr ) {
10732+ auto x = repeatNode;
10733+ str_list temp;
10734+ bool extraScope = false ;
10735+ if (expList) {
10736+ if (!currentScope ().lastStatement ) {
10737+ extraScope = true ;
10738+ temp.push_back (indent () + " do" s + nll (repeatNode));
10739+ pushScope ();
10740+ }
10741+ }
10742+ auto accumVar = getUnusedName (" _accum_" sv);
10743+ addToScope (accumVar);
10744+ auto lenVar = getUnusedName (" _len_" sv);
10745+ addToScope (lenVar);
10746+ auto breakLoopType = getBreakLoopType (repeatNode->body , accumVar);
10747+ _buf << indent () << " local " sv << accumVar << (hasBreakWithValue (breakLoopType) ? " " sv : " = { }" sv) << nll (repeatNode);
10748+ temp.emplace_back (clearBuf ());
10749+ _buf << indent () << " local " s << lenVar << " = 1" s << nll (repeatNode);
10750+ auto & lenAssign = temp.emplace_back (clearBuf ());
10751+ auto condStr = transformCondExp (repeatNode->condition , false );
10752+ temp.push_back (indent () + " repeat" s + nll (repeatNode));
10753+ pushScope ();
10754+ if (hasBreakWithValue (breakLoopType)) {
10755+ lenAssign.clear ();
10756+ transformLoopBody (repeatNode->body , temp, breakLoopType, ExpUsage::Common);
10757+ } else {
10758+ auto assignLeft = toAst<ExpList_t>(accumVar + ' [' + lenVar + ' ]' , x);
10759+ auto followStmt = toAst<Statement_t>(lenVar + " +=1" s, repeatNode);
10760+ assignLeft->followStmt = followStmt.get ();
10761+ transformLoopBody (repeatNode->body , temp, breakLoopType, ExpUsage::Assignment, assignLeft);
10762+ if (!assignLeft->followStmtProcessed ) {
10763+ lenAssign.clear ();
10764+ }
10765+ }
10766+ popScope ();
10767+ temp.push_back (indent () + " until " s + condStr + nlr (repeatNode));
10768+ if (expList) {
10769+ auto assign = x->new_ptr <Assign_t>();
10770+ assign->values .push_back (toAst<Exp_t>(accumVar, x));
10771+ auto assignment = x->new_ptr <ExpListAssign_t>();
10772+ assignment->expList .set (expList);
10773+ assignment->action .set (assign);
10774+ transformAssignment (assignment, temp);
10775+ if (extraScope) popScope ();
10776+ } else {
10777+ temp.push_back (indent () + " return " s + accumVar + nlr (repeatNode));
10778+ }
10779+ if (expList && extraScope) {
10780+ temp.push_back (indent () + " end" s + nlr (repeatNode));
10781+ }
10782+ out.push_back (join (temp));
10783+ }
10784+
10785+ void transformRepeatClosure (Repeat_t* repeatNode, str_list& out) {
10786+ auto x = repeatNode;
10787+ auto simpleValue = x->new_ptr <SimpleValue_t>();
10788+ simpleValue->value .set (repeatNode);
10789+ if (transformAsUpValueFunc (newExp (simpleValue, x), out)) {
10790+ return ;
10791+ }
10792+ str_list temp;
10793+ pushAnonFunctionScope ();
10794+ pushAnonVarArg ();
10795+ std::string& funcStart = temp.emplace_back ();
10796+ pushScope ();
10797+ auto accumVar = getUnusedName (" _accum_" sv);
10798+ addToScope (accumVar);
10799+ auto lenVar = getUnusedName (" _len_" sv);
10800+ addToScope (lenVar);
10801+ auto breakLoopType = getBreakLoopType (repeatNode->body , accumVar);
10802+ _buf << indent () << " local " sv << accumVar << (hasBreakWithValue (breakLoopType) ? " " sv : " = { }" sv) << nll (repeatNode);
10803+ temp.emplace_back (clearBuf ());
10804+ auto & lenAssign = temp.emplace_back (indent () + " local " s + lenVar + " = 1" s + nll (repeatNode));
10805+ auto condStr = transformCondExp (repeatNode->condition , false );
10806+ temp.push_back (indent () + " repeat" s + nll (repeatNode));
10807+ pushScope ();
10808+ if (hasBreakWithValue (breakLoopType)) {
10809+ lenAssign.clear ();
10810+ transformLoopBody (repeatNode->body , temp, breakLoopType, ExpUsage::Common);
10811+ } else {
10812+ auto assignLeft = toAst<ExpList_t>(accumVar + ' [' + lenVar + ' ]' , x);
10813+ auto followStmt = toAst<Statement_t>(lenVar + " +=1" s, repeatNode);
10814+ assignLeft->followStmt = followStmt.get ();
10815+ transformLoopBody (repeatNode->body , temp, breakLoopType, ExpUsage::Assignment, assignLeft);
10816+ if (!assignLeft->followStmtProcessed ) {
10817+ lenAssign.clear ();
10818+ }
10819+ }
10820+ popScope ();
10821+ temp.push_back (indent () + " until " s + condStr + nlr (repeatNode));
10822+ temp.push_back (indent () + " return " s + accumVar + nlr (repeatNode));
10823+ popScope ();
10824+ funcStart = anonFuncStart () + nll (repeatNode);
10825+ temp.push_back (indent () + anonFuncEnd ());
10826+ popAnonVarArg ();
10827+ popFunctionScope ();
10828+ out.push_back (join (temp));
10829+ }
10830+
1073010831 void transformRepeat (Repeat_t* repeat, str_list& out) {
1073110832 str_list temp;
1073210833 pushScope ();
0 commit comments