aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-05-16 01:03:05 +0800
committerLi Jin <dragon-fly@qq.com>2022-05-16 01:03:05 +0800
commitc4935826eea8df7a161b2b4ba9262dce66d9d366 (patch)
tree12f7fe952a777b98244253c5ecd3e0d0a73e8de8
parente9926f70a53639c09a5605f71a34ec370395f5a9 (diff)
downloadyuescript-c4935826eea8df7a161b2b4ba9262dce66d9d366.tar.gz
yuescript-c4935826eea8df7a161b2b4ba9262dce66d9d366.tar.bz2
yuescript-c4935826eea8df7a161b2b4ba9262dce66d9d366.zip
fix issue #102. fix `continue` statement locating issue.
-rw-r--r--spec/inputs/loops.yue8
-rw-r--r--spec/outputs/loops.lua23
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp84
3 files changed, 108 insertions, 7 deletions
diff --git a/spec/inputs/loops.yue b/spec/inputs/loops.yue
index 3191000..d03e661 100644
--- a/spec/inputs/loops.yue
+++ b/spec/inputs/loops.yue
@@ -109,6 +109,14 @@ repeat
109 print a 109 print a
110until a == 10 110until a == 10
111 111
112x = 0
113repeat
114 x += 1
115 y = x
116 continue if x < 5
117 print y
118until y == 10
119
112a = 3 120a = 3
113until a == 0 121until a == 0
114 a -= 1 122 a -= 1
diff --git a/spec/outputs/loops.lua b/spec/outputs/loops.lua
index aa69840..bcd559c 100644
--- a/spec/outputs/loops.lua
+++ b/spec/outputs/loops.lua
@@ -187,6 +187,7 @@ for i = 1, 10 do
187end 187end
188local a = 1 188local a = 1
189repeat 189repeat
190 local _cond_0
190 local _continue_0 = false 191 local _continue_0 = false
191 repeat 192 repeat
192 a = a + 1 193 a = a + 1
@@ -198,12 +199,32 @@ repeat
198 break 199 break
199 end 200 end
200 print(a) 201 print(a)
202 _cond_0 = a == 10
201 _continue_0 = true 203 _continue_0 = true
202 until true 204 until true
203 if not _continue_0 then 205 if not _continue_0 then
204 break 206 break
205 end 207 end
206until a == 10 208until _cond_0
209x = 0
210repeat
211 local _cond_0
212 local _continue_0 = false
213 repeat
214 x = x + 1
215 y = x
216 if x < 5 then
217 _continue_0 = true
218 break
219 end
220 print(y)
221 _cond_0 = y == 10
222 _continue_0 = true
223 until true
224 if not _continue_0 then
225 break
226 end
227until _cond_0
207a = 3 228a = 3
208while not (a == 0) do 229while not (a == 0) do
209 a = a - 1 230 a = a - 1
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 469dfea..6f641d9 100755
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -60,7 +60,7 @@ using namespace parserlib;
60 60
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.10.19"sv; 63const std::string_view version = "0.10.20"sv;
64const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
65 65
66class YueCompilerImpl { 66class YueCompilerImpl {
@@ -5257,9 +5257,8 @@ private:
5257 } 5257 }
5258 } 5258 }
5259 5259
5260 void transformLoopBody(ast_node* body, str_list& out, const std::string& appendContent, ExpUsage usage, ExpList_t* assignList = nullptr) { 5260 bool hasContinueStatement(ast_node* body) {
5261 str_list temp; 5261 return traversal::Stop == body->traverse([&](ast_node* node) {
5262 bool withContinue = traversal::Stop == body->traverse([&](ast_node* node) {
5263 if (auto stmt = ast_cast<Statement_t>(node)) { 5262 if (auto stmt = ast_cast<Statement_t>(node)) {
5264 if (stmt->content.is<BreakLoop_t>()) { 5263 if (stmt->content.is<BreakLoop_t>()) {
5265 return _parser.toString(stmt->content) == "continue"sv ? 5264 return _parser.toString(stmt->content) == "continue"sv ?
@@ -5268,10 +5267,20 @@ private:
5268 return traversal::Continue; 5267 return traversal::Continue;
5269 } 5268 }
5270 return traversal::Return; 5269 return traversal::Return;
5270 } else switch (node->getId()) {
5271 case id<FunLit_t>():
5272 case id<Invoke_t>():
5273 case id<InvokeArgs_t>():
5274 return traversal::Return;
5271 } 5275 }
5272 return traversal::Continue; 5276 return traversal::Continue;
5273 }); 5277 });
5278 }
5279
5280 void transformLoopBody(ast_node* body, str_list& out, const std::string& appendContent, ExpUsage usage, ExpList_t* assignList = nullptr) {
5281 str_list temp;
5274 bool extraDo = false; 5282 bool extraDo = false;
5283 bool withContinue = hasContinueStatement(body);
5275 if (withContinue) { 5284 if (withContinue) {
5276 if (auto block = ast_cast<Block_t>(body)) { 5285 if (auto block = ast_cast<Block_t>(body)) {
5277 if (!block->statements.empty()) { 5286 if (!block->statements.empty()) {
@@ -5316,6 +5325,65 @@ private:
5316 out.push_back(join(temp)); 5325 out.push_back(join(temp));
5317 } 5326 }
5318 5327
5328 std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) {
5329 str_list temp;
5330 bool extraDo = false;
5331 auto body = repeatNode->body->content.get();
5332 bool withContinue = hasContinueStatement(body);
5333 std::string conditionVar;
5334 if (withContinue) {
5335 if (auto block = ast_cast<Block_t>(body)) {
5336 if (!block->statements.empty()) {
5337 auto stmt = static_cast<Statement_t*>(block->statements.back());
5338 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) {
5339 extraDo = _parser.toString(breakLoop) == "break"sv;
5340 }
5341 }
5342 }
5343 conditionVar = getUnusedName("_cond_");
5344 forceAddToScope(conditionVar);
5345 auto continueVar = getUnusedName("_continue_"sv);
5346 forceAddToScope(continueVar);
5347 _continueVars.push(continueVar);
5348 _buf << indent() << "local "sv << conditionVar << nll(body);
5349 _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body);
5350 _buf << indent() << "repeat"sv << nll(body);
5351 pushScope();
5352 if (extraDo) {
5353 _buf << indent() << "do"sv << nll(body);
5354 pushScope();
5355 }
5356 temp.push_back(clearBuf());
5357 }
5358 transform_plain_body(body, temp, ExpUsage::Common);
5359 if (withContinue) {
5360 {
5361 auto assignment = toAst<ExpListAssign_t>(conditionVar + "=nil"s, body);
5362 auto assign = assignment->action.to<Assign_t>();
5363 assign->values.clear();
5364 assign->values.push_back(repeatNode->condition);
5365 transformAssignment(assignment, temp);
5366 auto assignCond = std::move(temp.back());
5367 temp.pop_back();
5368 temp.back().append(assignCond);
5369 }
5370 if (extraDo) {
5371 popScope();
5372 _buf << indent() << "end"sv << nll(body);
5373 }
5374 _buf << indent() << _continueVars.top() << " = true"sv << nll(body);
5375 popScope();
5376 _buf << indent() << "until true"sv << nlr(body);
5377 _buf << indent() << "if not "sv << _continueVars.top() << " then"sv << nlr(body);
5378 _buf << indent(1) << "break"sv << nlr(body);
5379 _buf << indent() << "end"sv << nlr(body);
5380 temp.push_back(clearBuf());
5381 _continueVars.pop();
5382 }
5383 out.push_back(join(temp));
5384 return conditionVar;
5385 }
5386
5319 void transformFor(For_t* forNode, str_list& out) { 5387 void transformFor(For_t* forNode, str_list& out) {
5320 str_list temp; 5388 str_list temp;
5321 transformForHead(forNode, temp); 5389 transformForHead(forNode, temp);
@@ -6838,8 +6906,12 @@ private:
6838 void transformRepeat(Repeat_t* repeat, str_list& out) { 6906 void transformRepeat(Repeat_t* repeat, str_list& out) {
6839 str_list temp; 6907 str_list temp;
6840 pushScope(); 6908 pushScope();
6841 transformLoopBody(repeat->body->content, temp, Empty, ExpUsage::Common); 6909 auto condVar = transformRepeatBody(repeat, temp);
6842 transformExp(repeat->condition, temp, ExpUsage::Closure); 6910 if (condVar.empty()) {
6911 transformExp(repeat->condition, temp, ExpUsage::Closure);
6912 } else {
6913 temp.push_back(condVar);
6914 }
6843 popScope(); 6915 popScope();
6844 _buf << indent() << "repeat"sv << nll(repeat); 6916 _buf << indent() << "repeat"sv << nll(repeat);
6845 _buf << temp.front(); 6917 _buf << temp.front();