Skip to content

Commit 87267ca

Browse files
committed
Updated repeat syntax functions.
1 parent a9d28cb commit 87267ca

9 files changed

Lines changed: 259 additions & 62 deletions

File tree

spec/inputs/loops.yue

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,4 +251,17 @@ do
251251
if value > 5
252252
item
253253

254-
254+
do
255+
repeat print 1 until true
256+
257+
x = repeat
258+
a = func!
259+
break a.x
260+
until a.v
261+
262+
items = repeat
263+
item = getItem!
264+
break unless item
265+
item if item.value > 0
266+
until false
267+

spec/outputs/5.1/loops.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,3 +587,31 @@ do
587587
end
588588
list = _accum_0
589589
end
590+
do
591+
repeat
592+
print(1)
593+
until true
594+
do
595+
local _accum_0
596+
repeat
597+
a = func()
598+
_accum_0 = a.x
599+
break
600+
until a.v
601+
x = _accum_0
602+
end
603+
local items
604+
local _accum_0 = { }
605+
local _len_0 = 1
606+
repeat
607+
local item = getItem()
608+
if not item then
609+
break
610+
end
611+
if item.value > 0 then
612+
_accum_0[_len_0] = item
613+
_len_0 = _len_0 + 1
614+
end
615+
until false
616+
items = _accum_0
617+
end

spec/outputs/loops.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,31 @@ do
468468
end
469469
list = _accum_0
470470
end
471+
do
472+
repeat
473+
print(1)
474+
until true
475+
do
476+
local _accum_0
477+
repeat
478+
a = func()
479+
_accum_0 = a.x
480+
break
481+
until a.v
482+
x = _accum_0
483+
end
484+
local items
485+
local _accum_0 = { }
486+
local _len_0 = 1
487+
repeat
488+
local item = getItem()
489+
if not item then
490+
break
491+
end
492+
if item.value > 0 then
493+
_accum_0[_len_0] = item
494+
_len_0 = _len_0 + 1
495+
end
496+
until false
497+
items = _accum_0
498+
end

spec/outputs/with.lua

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,12 @@ do
192192
local _with_0 = item
193193
do
194194
local _accum_0
195-
while true do
195+
repeat
196196
if _with_0.id > 0 then
197197
_accum_0 = _with_0.content
198198
break
199199
end
200-
end
200+
until true
201201
_with_0 = _accum_0
202202
end
203203
return _with_0
@@ -207,12 +207,12 @@ do
207207
local _with_0 = tb
208208
do
209209
local _accum_0
210-
while true do
210+
repeat
211211
if _with_0.v then
212212
_accum_0 = _with_0.a
213213
break
214214
end
215-
end
215+
until true
216216
_with_0 = _accum_0
217217
end
218218
a = _with_0
@@ -221,13 +221,12 @@ do
221221
while true do
222222
local _with_0 = tb
223223
local _accum_1
224-
while true do
224+
repeat
225225
if _with_0 ~= nil then
226226
_accum_1 = 1
227227
break
228228
end
229-
break
230-
end
229+
until true
231230
_with_0 = _accum_1
232231
_accum_0 = _with_0
233232
break

src/yuescript/yue_ast.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -527,20 +527,20 @@ std::string While_t::to_string(void* ud) const {
527527
}
528528
std::string Repeat_t::to_string(void* ud) const {
529529
auto info = reinterpret_cast<YueFormat*>(ud);
530-
str_list temp;
531-
if (body->content.is<Statement_t>()) {
532-
temp.emplace_back("repeat "s + body->to_string(ud));
530+
if (body.is<Statement_t>()) {
531+
return "repeat "s + body->to_string(ud) + " until "s + condition->to_string(ud);
533532
} else {
533+
str_list temp;
534534
temp.emplace_back("repeat"s);
535535
info->pushScope();
536536
temp.emplace_back(body->to_string(ud));
537537
if (temp.back().empty()) {
538538
temp.back() = info->ind() + "--"s;
539539
}
540540
info->popScope();
541+
temp.emplace_back(info->ind() + "until "s + condition->to_string(ud));
542+
return join(temp, "\n"sv);
541543
}
542-
temp.emplace_back(info->ind() + "until "s + condition->to_string(ud));
543-
return join(temp, "\n"sv);
544544
}
545545
std::string ForStepValue_t::to_string(void* ud) const {
546546
return value->to_string(ud);

src/yuescript/yue_ast.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ AST_NODE(While)
346346
AST_END(While)
347347

348348
AST_NODE(Repeat)
349-
ast_ptr<true, Body_t> body;
349+
ast_sel<true, Block_t, Statement_t> body;
350350
ast_ptr<true, Exp_t> condition;
351351
AST_MEMBER(Repeat, &body, &condition)
352352
AST_END(Repeat)
@@ -550,8 +550,8 @@ AST_NODE(SimpleValue)
550550
ast_sel<true,
551551
TableLit_t, ConstValue_t,
552552
If_t, Switch_t, With_t, ClassDecl_t,
553-
ForEach_t, For_t, While_t, Do_t, Try_t,
554-
UnaryValue_t,
553+
ForEach_t, For_t, While_t, Repeat_t,
554+
Do_t, Try_t, UnaryValue_t,
555555
TblComprehension_t, Comprehension_t,
556556
FunLit_t, Num_t, VarArg_t> value;
557557
AST_MEMBER(SimpleValue, &value)

src/yuescript/yue_compiler.cpp

Lines changed: 121 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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;
8282
const std::string_view extension = "yue"sv;
8383

8484
class 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--\nuntil 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--\nuntil 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

Comments
 (0)