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. --- spec/inputs/upvalue_func.yue | 13 ++-- spec/outputs/5.1/attrib.lua | 144 +++++++++++++++++------------------------ 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 +- 8 files changed, 121 insertions(+), 112 deletions(-) diff --git a/spec/inputs/upvalue_func.yue b/spec/inputs/upvalue_func.yue index d4b3273..378bf60 100644 --- a/spec/inputs/upvalue_func.yue +++ b/spec/inputs/upvalue_func.yue @@ -208,20 +208,21 @@ GameEngine\schedule (deltaTime) -> -- closure 1 -- test cases from issue do buff_strength = (char, item) -> - item.buffer.strength? char.stats.strength?::ref() + item.buffer.strength? char.stats.strength?::ref! local debug_env_before, debug_env_after exe_func = (func, env) -> ok, ... = try - debug_env_before(env) - func(env) - debug_env_after(env) + debug_env_before env + func env + debug_env_after env catch ex -- accessing ex and error error ex - return ex + -- implicit return + ex if ok return ... else - os.exit(1) + os.exit 1 diff --git a/spec/outputs/5.1/attrib.lua b/spec/outputs/5.1/attrib.lua index c48c72c..dc1285c 100644 --- a/spec/outputs/5.1/attrib.lua +++ b/spec/outputs/5.1/attrib.lua @@ -44,18 +44,6 @@ do } a, b = _obj_0[1], _obj_0[2] end -local _anon_func_0 = function(_close_1, error, f, _arg_0, ...) - do - local _ok_0 = _arg_0 - _close_1(f) - if _ok_0 then - return ... - else - return error(...) - end - end -end -local _anon_func_1 = function() end do local v if flag then @@ -82,28 +70,17 @@ do f = _with_0 end local _close_1 = assert(getmetatable(f).__close) - return _anon_func_0(_close_1, error, f, pcall(_anon_func_1)) + return (function(_arg_0, ...) + local _ok_0 = _arg_0 + _close_1(f) + if _ok_0 then + return ... + else + return error(...) + end + end)(pcall(function() end)) end)) end -local _anon_func_2 = function(_close_1, d, error, _arg_0, ...) - do - local _ok_0 = _arg_0 - _close_1(d) - if _ok_0 then - return ... - else - return error(...) - end - end -end -local _anon_func_3 = function(a, b) - if a ~= nil then - return a - else - return b - end -end -local _anon_func_4 = function() end do local a if true then @@ -133,37 +110,29 @@ do end end local d - if _anon_func_3(a, b) then + if (function() + if a ~= nil then + return a + else + return b + end + end)() then d = { value = value } end local _close_1 = assert(getmetatable(d).__close) - return _anon_func_2(_close_1, d, error, pcall(_anon_func_4)) + return (function(_arg_0, ...) + local _ok_0 = _arg_0 + _close_1(d) + if _ok_0 then + return ... + else + return error(...) + end + end)(pcall(function() end)) end)) end -local _anon_func_5 = function(_, _close_1, error, _arg_0, ...) - do - local _ok_0 = _arg_0 - _close_1(_) - if _ok_0 then - return ... - else - return error(...) - end - end -end -local _anon_func_6 = function(_, _close_2, error, _arg_0, ...) - do - local _ok_0 = _arg_0 - _close_2(_) - if _ok_0 then - return ... - else - return error(...) - end - end -end do local _ do @@ -187,14 +156,30 @@ do end }) local _close_1 = assert(getmetatable(_).__close) - return _anon_func_5(_, _close_1, error, pcall(function() + return (function(_arg_0, ...) + local _ok_0 = _arg_0 + _close_1(_) + if _ok_0 then + return ... + else + return error(...) + end + end)(pcall(function() local _ = setmetatable({ }, { __close = function() return print("first") end }) local _close_2 = assert(getmetatable(_).__close) - return _anon_func_6(_, _close_2, error, pcall(function() + return (function(_arg_0, ...) + local _ok_0 = _arg_0 + _close_2(_) + if _ok_0 then + return ... + else + return error(...) + end + end)(pcall(function() return print("third") end)) end)) @@ -211,29 +196,6 @@ def = function(item) _defers[#_defers + 1] = item return _defers end -local _anon_func_7 = function(_, _close_1, error, _arg_0, ...) - do - local _ok_0 = _arg_0 - _close_1(_) - if _ok_0 then - return ... - else - return error(...) - end - end -end -local _anon_func_8 = function(_, _close_2, error, _arg_0, ...) - do - local _ok_0 = _arg_0 - _close_2(_) - if _ok_0 then - return ... - else - return error(...) - end - end -end -local _anon_func_9 = function() end do local _ = def(function() return print(3) @@ -252,12 +214,28 @@ do return print(2) end) local _close_1 = assert(getmetatable(_).__close) - return _anon_func_7(_, _close_1, error, pcall(function() + return (function(_arg_0, ...) + local _ok_0 = _arg_0 + _close_1(_) + if _ok_0 then + return ... + else + return error(...) + end + end)(pcall(function() local _ = def(function() return print(1) end) local _close_2 = assert(getmetatable(_).__close) - return _anon_func_8(_, _close_2, error, pcall(_anon_func_9)) + return (function(_arg_0, ...) + local _ok_0 = _arg_0 + _close_2(_) + if _ok_0 then + return ... + else + return error(...) + end + end)(pcall(function() end)) end)) end)) end 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