diff options
author | Li Jin <dragon-fly@qq.com> | 2022-05-16 01:03:05 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-05-16 01:03:05 +0800 |
commit | c4935826eea8df7a161b2b4ba9262dce66d9d366 (patch) | |
tree | 12f7fe952a777b98244253c5ecd3e0d0a73e8de8 /src | |
parent | e9926f70a53639c09a5605f71a34ec370395f5a9 (diff) | |
download | yuescript-c4935826eea8df7a161b2b4ba9262dce66d9d366.tar.gz yuescript-c4935826eea8df7a161b2b4ba9262dce66d9d366.tar.bz2 yuescript-c4935826eea8df7a161b2b4ba9262dce66d9d366.zip |
fix issue #102. fix `continue` statement locating issue.
Diffstat (limited to 'src')
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 84 |
1 files changed, 78 insertions, 6 deletions
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 | ||
61 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
62 | 62 | ||
63 | const std::string_view version = "0.10.19"sv; | 63 | const std::string_view version = "0.10.20"sv; |
64 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
65 | 65 | ||
66 | class YueCompilerImpl { | 66 | class 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(); |