From 6af288657f5a7c43570ffbe91e1b727a4af5362d Mon Sep 17 00:00:00 2001 From: Li Jin Date: Sun, 29 Sep 2024 16:45:06 +0800 Subject: Disallowed some semantically incorrect syntax to improve code consistency. --- src/yuescript/ast.cpp | 4 +-- src/yuescript/parser.cpp | 6 ++--- src/yuescript/parser.hpp | 4 +-- src/yuescript/yue_ast.h | 2 ++ src/yuescript/yue_compiler.cpp | 58 +++++++++++++++++++++++++++++++----------- src/yuescript/yue_parser.cpp | 2 +- 6 files changed, 53 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/yuescript/ast.cpp b/src/yuescript/ast.cpp index 2bdac81..99ab8f5 100644 --- a/src/yuescript/ast.cpp +++ b/src/yuescript/ast.cpp @@ -54,8 +54,8 @@ bool ast_node::visit_child(const std::function&) { */ void ast_container::construct(ast_stack& st) { for (ast_member_vector::reverse_iterator it = m_members.rbegin(); - it != m_members.rend(); - ++it) { + it != m_members.rend(); + ++it) { ast_member* member = *it; member->construct(st); } diff --git a/src/yuescript/parser.cpp b/src/yuescript/parser.cpp index 5d0773c..f0ddd06 100644 --- a/src/yuescript/parser.cpp +++ b/src/yuescript/parser.cpp @@ -160,8 +160,8 @@ public: // execute all the parse procs void do_parse_procs(void* d) const { for (_match_vector::const_iterator it = m_matches.begin(); - it != m_matches.end(); - ++it) { + it != m_matches.end(); + ++it) { const _match& m = *it; parse_proc p = _private::get_parse_proc(*m.m_rule); p(m.m_begin, m.m_end, d); @@ -262,7 +262,7 @@ private: bool _parse(_context& con) const { for (auto it = m_string.begin(), end = m_string.end(); - ;) { + ;) { if (it == end) return true; if (con.end()) break; if (con.symbol() != *it) break; diff --git a/src/yuescript/parser.hpp b/src/yuescript/parser.hpp index 5ab327f..c544785 100644 --- a/src/yuescript/parser.hpp +++ b/src/yuescript/parser.hpp @@ -433,8 +433,8 @@ bool start_with(input& i, rule& g, error_list& el, void* st, void* ud); template T& operator<<(T& stream, const input_range& ir) { for (input::const_iterator it = ir.m_begin.m_it; - it != ir.m_end.m_it; - ++it) { + it != ir.m_end.m_it; + ++it) { stream << (typename T::char_type) * it; } return stream; diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index cffc92d..8063517 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -277,6 +277,7 @@ AST_END(ExpList) AST_NODE(Return) bool allowBlockMacroReturn = false; + bool explicitReturn = true; ast_sel valueList; AST_MEMBER(Return, &valueList) AST_END(Return) @@ -766,6 +767,7 @@ AST_NODE(FunLit) ast_ptr arrow; ast_ptr body; bool noRecursion = false; + bool isAnon = false; AST_MEMBER(FunLit, &argsDef, &defaultReturn, &arrow, &body) AST_END(FunLit) diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index b44b697..ef8e59e 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -75,7 +75,7 @@ static std::unordered_set Metamethods = { "close"s // Lua 5.4 }; -const std::string_view version = "0.25.3"sv; +const std::string_view version = "0.25.4"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -3777,6 +3777,7 @@ private: } case ExpUsage::Return: { auto ret = x->new_ptr(); + ret->explicitReturn = false; auto expListLow = x->new_ptr(); expListLow->exprs.push_back(arg); ret->valueList.set(expListLow); @@ -4007,6 +4008,7 @@ private: auto expListLow = exp->new_ptr(); expListLow->exprs.push_back(e); auto returnNode = exp->new_ptr(); + returnNode->explicitReturn = false; returnNode->valueList.set(expListLow); transformReturn(returnNode, out); break; @@ -4039,7 +4041,7 @@ private: }) != traversal::Stop; } - std::optional> getUpValueFuncFromBlock(Block_t* block, str_list* ensureArgListInTheEnd, bool noGlobalVarPassing) { + std::optional> getUpValueFuncFromBlock(Block_t* block, str_list* ensureArgListInTheEnd, bool noGlobalVarPassing, bool blockRewrite) { if (_funcLevel <= 1) return std::nullopt; auto result = block->traverse([&](ast_node* node) { switch (node->get_id()) { @@ -4138,6 +4140,7 @@ private: } } auto funLit = toAst("("s + join(args, ","sv) + ")-> nil"s, x); + funLit->isAnon = blockRewrite ? false : true; funLit->body->content.set(newBlock); funLit->noRecursion = true; auto simpleValue = x->new_ptr(); @@ -4159,16 +4162,17 @@ private: return std::nullopt; } - std::optional> upValueFuncFrom(Block_t* block, str_list* ensureArgListInTheEnd = nullptr, bool noGlobalVarPassing = false) { + std::optional> upValueFuncFromBlock(Block_t* block, str_list* ensureArgListInTheEnd, bool noGlobalVarPassing, bool blockRewrite) { if (checkUpValueFuncAvailable(block)) { - return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, noGlobalVarPassing); + return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, noGlobalVarPassing, blockRewrite); } return std::nullopt; } - std::optional> upValueFuncFrom(Exp_t* exp, str_list* ensureArgListInTheEnd = nullptr) { + std::optional> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { if (checkUpValueFuncAvailable(exp)) { auto returnNode = exp->new_ptr(); + returnNode->explicitReturn = false; auto returnList = exp->new_ptr(); returnList->exprs.push_back(exp); returnNode->valueList.set(returnList); @@ -4176,13 +4180,13 @@ private: auto stmt = exp->new_ptr(); stmt->content.set(returnNode); block->statements.push_back(stmt); - return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false); + return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); } return std::nullopt; } bool transformAsUpValueFunc(Exp_t* exp, str_list& out) { - auto result = upValueFuncFrom(exp); + auto result = upValueFuncFromExp(exp, nullptr, false); if (result) { auto [funcName, args] = std::move(*result); auto newChainValue = toAst(funcName + '(' + join(args, ","sv) + ')', exp); @@ -4258,6 +4262,7 @@ private: _buf << indent() << "else"s << nll(x); temp.push_back(clearBuf()); auto ret = x->new_ptr(); + ret->explicitReturn = false; auto retList = x->new_ptr(); retList->exprs.push_back(exp->nilCoalesed); ret->valueList.set(retList); @@ -4385,7 +4390,11 @@ private: } void transformFunLit(FunLit_t* funLit, str_list& out) { - pushUserFunctionScope(); + if (funLit->isAnon) { + pushAnonFunctionScope(); + } else { + pushUserFunctionScope(); + } _varArgs.push({false, false}); bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; pushScope(); @@ -4419,6 +4428,7 @@ private: } if (funLit->defaultReturn.is()) { auto returnNode = newBlock->new_ptr(); + returnNode->explicitReturn = false; returnNode->valueList.set(funLit->defaultReturn); auto stmt = newBlock->new_ptr(); stmt->content.set(returnNode); @@ -4594,7 +4604,7 @@ private: transformBlock(newBlock, out, usage, assignList, isRoot); return; } else if (auto expListAssign = stmt->content.as(); - expListAssign && expListAssign->action && expListAssign->action.is()) { + expListAssign && expListAssign->action && expListAssign->action.is()) { BLOCK_START auto unary = singleUnaryExpFrom(expListAssign->expList->exprs.back()); BREAK_IF(!unary); @@ -4693,7 +4703,7 @@ private: doNode->body.set(newBody); auto simpleValue = x->new_ptr(); simpleValue->value.set(doNode); - if (auto result = upValueFuncFrom(newExp(simpleValue, x), &argNames)) { + if (auto result = upValueFuncFromExp(newExp(simpleValue, x), &argNames, true)) { auto [funcName, args] = std::move(*result); str_list finalArgs; for (const auto& arg : args) { @@ -4903,6 +4913,7 @@ private: auto expListLow = x->new_ptr(); expListLow->exprs.dup(expList->exprs); auto returnNode = x->new_ptr(); + returnNode->explicitReturn = false; returnNode->valueList.set(expListLow); returnNode->allowBlockMacroReturn = true; last->content.set(returnNode); @@ -5258,6 +5269,11 @@ private: if (!target) target = returnNode; throw CompileError("can not mix use of return and export statements in module scope"sv, target); } + if (returnNode->explicitReturn && _funcStates.top().isAnon) { + ast_node* target = returnNode->valueList.get(); + if (!target) target = returnNode; + throw CompileError("explicit return statement is not allowed in this context"sv, target); + } if (auto valueList = returnNode->valueList.as()) { if (valueList->exprs.size() == 1) { auto exp = static_cast(valueList->exprs.back()); @@ -5712,6 +5728,7 @@ private: case ExpUsage::Closure: { auto exp = newExp(partTwo, x); auto ret = x->new_ptr(); + ret->explicitReturn = false; auto expListLow = x->new_ptr(); expListLow->exprs.push_back(exp); ret->valueList.set(expListLow); @@ -5810,6 +5827,7 @@ private: case ExpUsage::Closure: case ExpUsage::Return: { auto returnNode = x->new_ptr(); + returnNode->explicitReturn = false; auto expListLow = x->new_ptr(); expListLow->exprs.push_back(funLit); returnNode->valueList.set(expListLow); @@ -5944,6 +5962,7 @@ private: switch (usage) { case ExpUsage::Closure: { auto returnNode = x->new_ptr(); + returnNode->explicitReturn = false; auto values = x->new_ptr(); values->exprs.push_back(newChainExp); returnNode->valueList.set(values); @@ -5957,6 +5976,7 @@ private: } case ExpUsage::Return: { auto returnNode = x->new_ptr(); + returnNode->explicitReturn = false; auto values = x->new_ptr(); values->exprs.push_back(newChainExp); returnNode->valueList.set(values); @@ -6629,6 +6649,7 @@ private: auto expListLow = x->new_ptr(); expListLow->exprs.push_back(node); auto returnNode = x->new_ptr(); + returnNode->explicitReturn = false; returnNode->valueList.set(expListLow); transformReturn(returnNode, out); break; @@ -7612,6 +7633,7 @@ private: simpleValue->value.set(tableLit); auto exp = newExp(simpleValue, x); auto returnNode = x->new_ptr(); + returnNode->explicitReturn = false; auto expList = x->new_ptr(); expList->exprs.push_back(exp); returnNode->valueList.set(expList); @@ -8296,6 +8318,7 @@ private: } else { auto accum = transformForInner(forNode, temp); auto returnNode = x->new_ptr(); + returnNode->explicitReturn = false; auto expListLow = toAst(accum, x); returnNode->valueList.set(expListLow); transformReturn(returnNode, temp); @@ -8395,6 +8418,7 @@ private: } else { auto accum = transformForEachInner(forEach, temp); auto returnNode = x->new_ptr(); + returnNode->explicitReturn = false; auto expListLow = toAst(accum, x); returnNode->valueList.set(expListLow); transformReturn(returnNode, temp); @@ -9618,11 +9642,13 @@ private: auto x = tryNode; ast_ptr errHandler; if (tryNode->catchBlock) { - auto errHandleStr = "("s + variableToString(tryNode->catchBlock->err) + ")->"s; - errHandler.set(toAst(errHandleStr, x->func)); + auto catchBlock = tryNode->catchBlock.get(); + auto errHandleStr = "("s + variableToString(catchBlock->err) + ")->"s; + errHandler.set(toAst(errHandleStr, catchBlock)); auto funLit = simpleSingleValueFrom(errHandler)->value.to(); - auto body = x->new_ptr(); - body->content.set(tryNode->catchBlock->block); + funLit->isAnon = true; + auto body = catchBlock->block->new_ptr(); + body->content.set(catchBlock->block); funLit->body.set(body); } ast_sel tryFunc; @@ -9700,7 +9726,7 @@ private: } if (auto tryBlock = tryFunc.as()) { if (getLuaTarget(tryBlock) >= 502 || !errHandler) { - if (auto result = upValueFuncFrom(tryBlock, nullptr, true)) { + if (auto result = upValueFuncFromBlock(tryBlock, nullptr, true, false)) { auto [funcName, args] = std::move(*result); if (errHandler) { auto xpcall = toAst("xpcall()", x); @@ -9729,6 +9755,7 @@ private: } auto tryExp = toAst("->"sv, x); auto funLit = simpleSingleValueFrom(tryExp)->value.to(); + funLit->isAnon = true; auto body = x->new_ptr(); body->content.set(tryBlock); funLit->body.set(body); @@ -9762,6 +9789,7 @@ private: if (errHandler && getLuaTarget(x) < 502) { auto tryExp = toAst("->"sv, x); auto funLit = simpleSingleValueFrom(tryExp)->value.to(); + funLit->isAnon = true; auto expList = x->new_ptr(); expList->exprs.push_back(tryFunc); auto expListAssign = x->new_ptr(); diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 93787cd..d7af780 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -1167,7 +1167,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCo } auto line = Converter{}.to_bytes(std::wstring(begin, end)); while (col < static_cast(line.size()) - && (line[col] == ' ' || line[col] == '\t')) { + && (line[col] == ' ' || line[col] == '\t')) { col++; } Utils::replace(line, "\t"sv, " "sv); -- cgit v1.2.3-55-g6feb