From 28bae6517f43c384a828df62b727517e26b3af9b Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 19 Mar 2025 14:52:54 +0800 Subject: Fixed issue #194, #195. --- LICENSE | 2 +- spec/inputs/assign.yue | 18 +++++++++ spec/outputs/assign.lua | 25 ++++++++++++ spec/outputs/codes_from_doc.lua | 18 +++------ spec/outputs/codes_from_doc_zh.lua | 18 +++------ spec/outputs/macro.lua | 24 ++++-------- spec/outputs/plus.lua | 3 +- spec/outputs/unicode/macro.lua | 6 +-- spec/outputs/unicode/plus.lua | 3 +- src/yuescript/yue_compiler.cpp | 78 ++++++++++++++++++++++++-------------- src/yuescript/yue_parser.cpp | 2 +- src/yuescript/yuescript.h | 8 ++-- 12 files changed, 123 insertions(+), 82 deletions(-) diff --git a/LICENSE b/LICENSE index f1cdba4..ca28207 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017-2025 Li Jin +Copyright (c) 2017-2025 Li Jin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/spec/inputs/assign.yue b/spec/inputs/assign.yue index 514aeed..ad1eda3 100644 --- a/spec/inputs/assign.yue +++ b/spec/inputs/assign.yue @@ -109,4 +109,22 @@ do val = 123 a = b = c = val +do + -- update + a ..= "abc" + a //= 2 + a or= def + a and= false + a >>= 10 + a <<= 10 + a.b.c ??= 123 + a.b.c += 1 + a.b.c -= 2 + a.b.c *= 3 + a.b.c /= 4 + a.b.c %= 5 + a &= 6 + a |= 7 + a ^= 8 + nil diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua index 162a563..f889865 100644 --- a/spec/outputs/assign.lua +++ b/spec/outputs/assign.lua @@ -181,5 +181,30 @@ return _(function() local b = val local c = val end + do + local a = a .. "abc" + a = a // 2 + a = a or def + a = a and false + a = a >> 10 + a = a << 10 + local _obj_0 = a.b + if _obj_0.c == nil then + _obj_0.c = 123 + end + local _obj_1 = a.b + _obj_1.c = _obj_1.c + 1 + local _obj_2 = a.b + _obj_2.c = _obj_2.c - 2 + local _obj_3 = a.b + _obj_3.c = _obj_3.c * 3 + local _obj_4 = a.b + _obj_4.c = _obj_4.c / 4 + local _obj_5 = a.b + _obj_5.c = _obj_5.c % 5 + a = a & 6 + a = a | 7 + a = a ^ 8 + end return nil end) diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua index 74db469..a37b459 100644 --- a/spec/outputs/codes_from_doc.lua +++ b/spec/outputs/codes_from_doc.lua @@ -467,8 +467,7 @@ local x = f() local y = x local z = x do - local a - a = 1 + local a = 1 local x, y, z print("forward declare all variables as locals") x = function() @@ -478,8 +477,7 @@ do instance = Item:new() end do - local X - X = 1 + local X = 1 local B print("only forward declare upper case variables") local a = 1 @@ -499,8 +497,7 @@ do print("only declare upper case variables as globals") local a = 1 local B = 2 - local Temp - Temp = "a local value" + local Temp = "a local value" end local thing = { 1, @@ -2478,8 +2475,7 @@ local x = f() local y = x local z = x do - local a - a = 1 + local a = 1 local x, y, z print("forward declare all variables as locals") x = function() @@ -2489,8 +2485,7 @@ do instance = Item:new() end do - local X - X = 1 + local X = 1 local B print("only forward declare upper case variables") local a = 1 @@ -2510,8 +2505,7 @@ do print("only declare upper case variables as globals") local a = 1 local B = 2 - local Temp - Temp = "a local value" + local Temp = "a local value" end local thing = { 1, diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index 1a10555..a23044d 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua @@ -467,8 +467,7 @@ local x = f() local y = x local z = x do - local a - a = 1 + local a = 1 local x, y, z print("预先声明后续所有变量为局部变量") x = function() @@ -478,8 +477,7 @@ do instance = Item:new() end do - local X - X = 1 + local X = 1 local B print("只预先声明后续大写的变量为局部变量") local a = 1 @@ -499,8 +497,7 @@ do print("只预先声明大写的变量为全局变量") local a = 1 local B = 2 - local Temp - Temp = "一个局部值" + local Temp = "一个局部值" end local thing = { 1, @@ -2472,8 +2469,7 @@ local x = f() local y = x local z = x do - local a - a = 1 + local a = 1 local x, y, z print("预先声明后续所有变量为局部变量") x = function() @@ -2483,8 +2479,7 @@ do instance = Item:new() end do - local X - X = 1 + local X = 1 local B print("只预先声明后续大写的变量为局部变量") local a = 1 @@ -2504,8 +2499,7 @@ do print("只预先声明大写的变量为全局变量") local a = 1 local B = 2 - local Temp - Temp = "一个局部值" + local Temp = "一个局部值" end local thing = { 1, diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua index aa74ed9..4d31574 100644 --- a/spec/outputs/macro.lua +++ b/spec/outputs/macro.lua @@ -191,13 +191,11 @@ end do local a = 8 a = (function() - local a - a = 1 + local a = 1 return a + 1 end)() a = a + (function() - local a - a = 1 + local a = 1 return a + 1 end)() print(a) @@ -274,18 +272,12 @@ local result = ((((((origin.transform.root.gameObject:Parents()):Descendants()): end)):Destroy() do do - local _1 - _1 = origin.transform.root.gameObject:Parents() - local _2 - _2 = _1:Descendants() - local _3 - _3 = _2:SelectEnable() - local _4 - _4 = _3:SelectVisible() - local _5 - _5 = _4:TagEqual("fx") - local _6 - _6 = _5:Where(function(x) + local _1 = origin.transform.root.gameObject:Parents() + local _2 = _1:Descendants() + local _3 = _2:SelectEnable() + local _4 = _3:SelectVisible() + local _5 = _4:TagEqual("fx") + local _6 = _5:Where(function(x) return x.name:EndsWith("(Clone)") end) _6:Destroy() diff --git a/spec/outputs/plus.lua b/spec/outputs/plus.lua index bd89bfe..dda0660 100644 --- a/spec/outputs/plus.lua +++ b/spec/outputs/plus.lua @@ -65,7 +65,6 @@ backpack = { local start = { something = "cold" } -local bathe -bathe = { +local bathe = { on = "fire" } diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua index e2195e4..099080f 100644 --- a/spec/outputs/unicode/macro.lua +++ b/spec/outputs/unicode/macro.lua @@ -167,13 +167,11 @@ end do local _u53d8_u91cfa = 8 _u53d8_u91cfa = (function() - local _u53d8_u91cfa - _u53d8_u91cfa = 1 + local _u53d8_u91cfa = 1 return _u53d8_u91cfa + 1 end)() _u53d8_u91cfa = _u53d8_u91cfa + (function() - local _u53d8_u91cfa - _u53d8_u91cfa = 1 + local _u53d8_u91cfa = 1 return _u53d8_u91cfa + 1 end)() _u6253_u5370(_u53d8_u91cfa) diff --git a/spec/outputs/unicode/plus.lua b/spec/outputs/unicode/plus.lua index 75e4aac..adce62e 100644 --- a/spec/outputs/unicode/plus.lua +++ b/spec/outputs/unicode/plus.lua @@ -67,7 +67,6 @@ _u80cc_u5305 = { local _u5f00_u59cb = { ["东西"] = "冷" } -local _u6d17_u6fa1 -_u6d17_u6fa1 = { +local _u6d17_u6fa1 = { ["在"] = "火" } diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index e7fe0c0..3d98fbc 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.27.0"sv; +const std::string_view version = "0.27.1"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -1486,7 +1486,7 @@ private: } } - bool isPureBackcall(Exp_t* exp) const { + bool isPurePipeChain(Exp_t* exp) const { return exp->opValues.empty() && exp->pipeExprs.size() > 1; } @@ -1869,7 +1869,7 @@ private: } } else if (expList->exprs.size() == 1) { auto exp = static_cast(expList->exprs.back()); - if (isPureBackcall(exp)) { + if (isPurePipeChain(exp)) { transformExp(exp, out, ExpUsage::Common); break; } @@ -2061,7 +2061,7 @@ private: } } - void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { + bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { checkAssignable(assignment->expList); BLOCK_START auto assign = ast_cast(assignment->action); @@ -2176,7 +2176,7 @@ private: temp.push_back(indent() + "end"s + nll(assignment)); } out.push_back(join(temp)); - return; + return false; BLOCK_END } { @@ -2248,7 +2248,7 @@ private: transformAssignment(afterAssignment, temp); } out.push_back(join(temp)); - return; + return false; } else if (ast_is(chainValue->items.back())) { str_list temp; auto [beforeAssignment, afterAssignment] = splitAssignment(); @@ -2300,7 +2300,7 @@ private: transformAssignment(afterAssignment, temp); } out.push_back(join(temp)); - return; + return false; } else { break; } @@ -2322,7 +2322,7 @@ private: std::string preDefine = getPreDefineLine(assignment); transformIf(ifNode, out, ExpUsage::Assignment, assignList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto switchNode = static_cast(value); @@ -2330,7 +2330,7 @@ private: std::string preDefine = getPreDefineLine(assignment); transformSwitch(switchNode, out, ExpUsage::Assignment, assignList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto withNode = static_cast(value); @@ -2338,7 +2338,7 @@ private: std::string preDefine = getPreDefineLine(assignment); transformWith(withNode, out, expList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto expList = assignment->expList.get(); @@ -2346,7 +2346,7 @@ private: std::string preDefine = getPreDefineLine(assignment); transformDo(doNode, out, ExpUsage::Assignment, expList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto comp = static_cast(value); @@ -2358,42 +2358,42 @@ private: } else { transformComprehension(comp, out, ExpUsage::Assignment, expList); } - return; + return false; } case id(): { auto expList = assignment->expList.get(); std::string preDefine = getPreDefineLine(assignment); transformTblComprehension(static_cast(value), out, ExpUsage::Assignment, expList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto expList = assignment->expList.get(); std::string preDefine = getPreDefineLine(assignment); transformForInPlace(static_cast(value), out, expList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto expList = assignment->expList.get(); std::string preDefine = getPreDefineLine(assignment); transformForEachInPlace(static_cast(value), out, expList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto expList = assignment->expList.get(); std::string preDefine = getPreDefineLine(assignment); transformClassDecl(static_cast(value), out, ExpUsage::Assignment, expList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto expList = assignment->expList.get(); std::string preDefine = getPreDefineLine(assignment); transformWhileInPlace(static_cast(value), out, expList); out.back().insert(0, preDefine); - return; + return false; } case id(): { auto tableLit = static_cast(value); @@ -2402,7 +2402,7 @@ private: std::string preDefine = getPreDefineLine(assignment); transformSpreadTable(tableLit->values.objects(), out, ExpUsage::Assignment, expList, false); out.back().insert(0, preDefine); - return; + return false; } break; } @@ -2413,31 +2413,31 @@ private: std::string preDefine = getPreDefineLine(assignment); transformSpreadTable(tableBlock->values.objects(), out, ExpUsage::Assignment, expList, false); out.back().insert(0, preDefine); - return; + return false; } break; } } auto exp = ast_cast(value); BREAK_IF(!exp); - if (isPureBackcall(exp)) { + if (isPurePipeChain(exp)) { auto expList = assignment->expList.get(); transformExp(exp, out, ExpUsage::Assignment, expList); - return; + return false; } else if (isPureNilCoalesed(exp)) { auto expList = assignment->expList.get(); transformNilCoalesedExp(exp, out, ExpUsage::Assignment, expList); - return; + return false; } else if (auto unary = unaryGeneratingAnonFunc(exp)) { std::string preDefine = getPreDefineLine(assignment); auto expList = assignment->expList.get(); transformUnaryExp(unary, out, ExpUsage::Assignment, expList); out.back().insert(0, preDefine); - return; + return false; } else if (isConditionChaining(exp)) { auto expList = assignment->expList.get(); transformExp(exp, out, ExpUsage::Assignment, expList); - return; + return false; } auto singleVal = singleValueFrom(exp); BREAK_IF(!singleVal); @@ -2451,13 +2451,13 @@ private: std::string preDefine = getPreDefineLine(assignment); transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); out.back().insert(0, preDefine); - return; + return false; } case ChainType::HasKeyword: case ChainType::HasUnicode: case ChainType::Macro: transformChainValue(chainValue, out, ExpUsage::Assignment, expList); - return; + return false; case ChainType::Common: case ChainType::EndWithEOP: case ChainType::Metatable: @@ -2468,6 +2468,7 @@ private: auto info = extractDestructureInfo(assignment, false, optionalDestruct); if (info.destructures.empty()) { transformAssignmentCommon(assignment, out); + return true; } else { auto x = assignment; str_list temp; @@ -2733,6 +2734,7 @@ private: } out.push_back(join(temp)); } + return false; } void transformAssignItem(ast_node* value, str_list& out) { @@ -5313,7 +5315,7 @@ private: if (auto valueList = returnNode->valueList.as()) { if (valueList->exprs.size() == 1) { auto exp = static_cast(valueList->exprs.back()); - if (isPureBackcall(exp)) { + if (isPurePipeChain(exp)) { transformExp(exp, out, ExpUsage::Return); return; } else if (isPureNilCoalesed(exp)) { @@ -10676,6 +10678,7 @@ private: void transformLocal(Local_t* local, str_list& out) { str_list temp; + bool defined = local->defined; if (!local->defined) { local->defined = true; transformLocalDef(local, temp); @@ -10704,7 +10707,26 @@ private: assign->values.push_back(tableBlock); } assignment->action.set(assign); - transformAssignment(assignment, temp); + bool oneLined = transformAssignment(assignment, temp); + for (auto val : assign->values.objects()) { + if (auto value = singleValueFrom(val)) { + if (auto spValue = value->item.as()) { + if (auto funLit = spValue->value.as()) { + if (!funLit->noRecursion) { + oneLined = false; + } + break; + } + } + } + } + if (!defined && oneLined && temp.size() == 2) { + auto pos = temp.back().find_first_not_of(" \t"sv); + if (pos != std::string::npos) { + temp.back().insert(pos, "local "); + temp.pop_front(); + } + } } break; } diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 5993ed5..ceb1f7c 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -519,7 +519,7 @@ YueParser::YueParser() { UpdateOp = expr("..") | "//" | "or" | "and" | ">>" | "<<" | "??" | - set("+-*/%&|"); + set("+-*/%&|^"); Update = UpdateOp >> '=' >> space >> Exp; diff --git a/src/yuescript/yuescript.h b/src/yuescript/yuescript.h index ebe90cb..83a4350 100644 --- a/src/yuescript/yuescript.h +++ b/src/yuescript/yuescript.h @@ -187,10 +187,10 @@ local function dump(what) depth = depth or 0 local t = type(what) if "string" == t then - return "\"" .. tostring(what) .. "\"\n" + return "\"" .. tostring(what) .. "\"" elseif "table" == t then if seen[what] then - return "recursion(" .. tostring(what) .. ")...\n" + return "recursion(" .. tostring(what) .. ")..." end seen[what] = true depth = depth + 1 @@ -199,9 +199,9 @@ local function dump(what) insert(lines, ('\t'):rep(depth) .. "[" .. tostring(k) .. "] = " .. _dump(v, depth)) end seen[what] = false - return "{\n" .. concat(lines) .. ('\t'):rep(depth - 1) .. "}\n" + return "{\n" .. concat(lines, "\n") .. "\n" .. ('\t'):rep(depth - 1) .. "}" else - return tostring(what) .. "\n" + return tostring(what) end end return _dump(what) -- cgit v1.2.3-55-g6feb