From 0e72454a11f65d9ac800dedb698ddfcc15933785 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 4 Jun 2025 16:07:06 +0800 Subject: Added more reversed index support for slice. [skip CI] --- spec/outputs/codes_from_doc.lua | 24 ++++----- spec/outputs/codes_from_doc_zh.lua | 24 ++++----- spec/outputs/comprehension.lua | 10 +++- spec/outputs/destructure.lua | 12 ++--- spec/outputs/lists.lua | 43 +++++++++------- spec/outputs/switch.lua | 4 +- spec/outputs/unicode/comprehension.lua | 10 +++- spec/outputs/unicode/lists.lua | 23 +++++---- src/yuescript/yue_compiler.cpp | 91 ++++++++++++++++++++++++++++++++-- 9 files changed, 174 insertions(+), 67 deletions(-) diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua index b8dd9b7..e137823 100644 --- a/spec/outputs/codes_from_doc.lua +++ b/spec/outputs/codes_from_doc.lua @@ -1062,8 +1062,7 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -local _max_0 = 5 -for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do +for _index_0 = 1, 5 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -1073,7 +1072,8 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -for _index_0 = 2, #_list_0 do +local _max_0 = #_list_0 +for _index_0 = 2, _max_0 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -1083,7 +1083,8 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -for _index_0 = 1, #_list_0, 2 do +local _max_0 = #_list_0 +for _index_0 = 1, _max_0, 2 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -1099,8 +1100,7 @@ for key, value in pairs(object) do print(key, value) end local _list_0 = items -local _max_0 = 4 -for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do +for _index_0 = 2, 4 do local item = _list_0[_index_0] print(item) end @@ -3332,8 +3332,7 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -local _max_0 = 5 -for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do +for _index_0 = 1, 5 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -3343,7 +3342,8 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -for _index_0 = 2, #_list_0 do +local _max_0 = #_list_0 +for _index_0 = 2, _max_0 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -3353,7 +3353,8 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -for _index_0 = 1, #_list_0, 2 do +local _max_0 = #_list_0 +for _index_0 = 1, _max_0, 2 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -3369,8 +3370,7 @@ for key, value in pairs(object) do print(key, value) end local _list_0 = items -local _max_0 = 4 -for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do +for _index_0 = 2, 4 do local item = _list_0[_index_0] print(item) end diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index 80644a5..c6ba43d 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua @@ -1056,8 +1056,7 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -local _max_0 = 5 -for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do +for _index_0 = 1, 5 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -1067,7 +1066,8 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -for _index_0 = 2, #_list_0 do +local _max_0 = #_list_0 +for _index_0 = 2, _max_0 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -1077,7 +1077,8 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -for _index_0 = 1, #_list_0, 2 do +local _max_0 = #_list_0 +for _index_0 = 1, _max_0, 2 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -1093,8 +1094,7 @@ for key, value in pairs(object) do print(key, value) end local _list_0 = items -local _max_0 = 4 -for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do +for _index_0 = 2, 4 do local item = _list_0[_index_0] print(item) end @@ -3320,8 +3320,7 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -local _max_0 = 5 -for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do +for _index_0 = 1, 5 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -3331,7 +3330,8 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -for _index_0 = 2, #_list_0 do +local _max_0 = #_list_0 +for _index_0 = 2, _max_0 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -3341,7 +3341,8 @@ local slice local _accum_0 = { } local _len_0 = 1 local _list_0 = items -for _index_0 = 1, #_list_0, 2 do +local _max_0 = #_list_0 +for _index_0 = 1, _max_0, 2 do local item = _list_0[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -3357,8 +3358,7 @@ for key, value in pairs(object) do print(key, value) end local _list_0 = items -local _max_0 = 4 -for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do +for _index_0 = 2, 4 do local item = _list_0[_index_0] print(item) end diff --git a/spec/outputs/comprehension.lua b/spec/outputs/comprehension.lua index ac4f9d8..663bd44 100644 --- a/spec/outputs/comprehension.lua +++ b/spec/outputs/comprehension.lua @@ -243,8 +243,11 @@ end do local _accum_0 = { } local _len_0 = 1 + local _min_0 = 1 + 2 local _max_0 = 3 + 4 - for _index_0 = 1 + 2, _max_0 < 0 and #items + _max_0 + 1 or _max_0 do + _min_0 = _min_0 < 0 and #items + _min_0 + 1 or _min_0 + _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 + for _index_0 = _min_0, _max_0 do local item = items[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 @@ -254,8 +257,11 @@ end do local _accum_0 = { } local _len_0 = 1 + local _min_0 = hello() * 4 local _max_0 = 2 - thing[4] - for _index_0 = hello() * 4, _max_0 < 0 and #items + _max_0 + 1 or _max_0 do + _min_0 = _min_0 < 0 and #items + _min_0 + 1 or _min_0 + _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 + for _index_0 = _min_0, _max_0 do local item = items[_index_0] _accum_0[_len_0] = item _len_0 = _len_0 + 1 diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 216d921..ba216b5 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua @@ -631,8 +631,8 @@ do local vipStart, regulars, vipEnd = clients[1], (function() local _accum_0 = { } local _len_0 = 1 - local _max_0 = -2 - for _index_0 = 2, _max_0 < 0 and #clients + _max_0 + 1 or _max_0 do + local _max_0 = #clients + -2 + 1 + for _index_0 = 2, _max_0 do local _item_0 = clients[_index_0] _accum_0[_len_0] = _item_0 _len_0 = _len_0 + 1 @@ -688,8 +688,8 @@ do local _accum_0 = { } local _len_0 = 1 local _list_0 = tb - local _max_0 = -2 - for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 + 1 or _max_0 do + local _max_0 = #_list_0 + -2 + 1 + for _index_0 = 2, _max_0 do local _item_0 = _list_0[_index_0] _accum_0[_len_0] = _item_0 _len_0 = _len_0 + 1 @@ -702,8 +702,8 @@ do a, abc, b, def, sub, d, e = _obj_0[1], _obj_0.abc, _obj_0[2], _obj_0.def, (function() local _accum_0 = { } local _len_0 = 1 - local _max_0 = -3 - for _index_0 = 3, _max_0 < 0 and #_obj_0 + _max_0 + 1 or _max_0 do + local _max_0 = #_obj_0 + -3 + 1 + for _index_0 = 3, _max_0 do local _item_0 = _obj_0[_index_0] _accum_0[_len_0] = _item_0 _len_0 = _len_0 + 1 diff --git a/spec/outputs/lists.lua b/spec/outputs/lists.lua index 1bdfa3e..2ed7b95 100644 --- a/spec/outputs/lists.lua +++ b/spec/outputs/lists.lua @@ -230,31 +230,36 @@ x = { 6, 7 } -local _max_0 = -5 -for _index_0 = 2, _max_0 < 0 and #x + _max_0 + 1 or _max_0, 2 do +local _max_0 = #x + -5 + 1 +for _index_0 = 2, _max_0, 2 do local y = x[_index_0] print(y) end -local _max_1 = 3 -for _index_0 = 1, _max_1 < 0 and #x + _max_1 + 1 or _max_1 do +for _index_0 = 1, 3 do local y = x[_index_0] print(y) end -for _index_0 = 2, #x do +local _max_1 = #x +for _index_0 = 2, _max_1 do local y = x[_index_0] print(y) end -for _index_0 = 1, #x, 2 do +local _max_2 = #x +for _index_0 = 1, _max_2, 2 do local y = x[_index_0] print(y) end -for _index_0 = 2, #x, 2 do +local _max_3 = #x +for _index_0 = 2, _max_3, 2 do local y = x[_index_0] print(y) end local a, b, c = 1, 5, 2 -local _max_2 = b -for _index_0 = a, _max_2 < 0 and #x + _max_2 + 1 or _max_2, c do +local _min_0 = a +local _max_4 = b +_min_0 = _min_0 < 0 and #x + _min_0 + 1 or _min_0 +_max_4 = _max_4 < 0 and #x + _max_4 + 1 or _max_4 +for _index_0 = _min_0, _max_4, c do local y = x[_index_0] print(y) end @@ -287,7 +292,10 @@ do a }) local _list_0 = f - for _index_0 = a, #_list_0 do + local _min_1 = a + local _max_5 = #_list_0 + _min_1 = _min_1 < 0 and #_list_0 + _min_1 + 1 or _min_1 + for _index_0 = _min_1, _max_5 do local v = _list_0[_index_0] print(v) end @@ -339,8 +347,8 @@ do do local _accum_0 = { } local _len_0 = 1 - local _max_3 = -2 - for _index_0 = 2, _max_3 < 0 and #transactions + _max_3 + 1 or _max_3 do + local _max_5 = #transactions + -2 + 1 + for _index_0 = 2, _max_5 do local _item_0 = transactions[_index_0] _accum_0[_len_0] = _item_0 _len_0 = _len_0 + 1 @@ -405,7 +413,8 @@ do cloneList1 = function(list) local _accum_0 = { } local _len_0 = 1 - for _index_0 = 1, #list do + local _max_5 = #list + for _index_0 = 1, _max_5 do local _item_0 = list[_index_0] _accum_0[_len_0] = _item_0 _len_0 = _len_0 + 1 @@ -471,8 +480,8 @@ local _anon_func_1 = function(a) local _accum_0 = { } local _len_0 = 1 local _list_0 = a.b.c - local _max_3 = -5 - for _index_0 = 5, _max_3 < 0 and #_list_0 + _max_3 + 1 or _max_3 do + local _max_5 = #_list_0 + -5 + 1 + for _index_0 = 5, _max_5 do local _item_1 = _list_0[_index_0] _accum_0[_len_0] = _item_1 _len_0 = _len_0 + 1 @@ -491,8 +500,8 @@ local _anon_func_2 = function(x) if _obj_2 ~= nil then local _accum_0 = { } local _len_0 = 1 - local _max_3 = -3 - for _index_0 = 1, _max_3 < 0 and #_obj_2 + _max_3 + 1 or _max_3 do + local _max_5 = #_obj_2 + -3 + 1 + for _index_0 = 1, _max_5 do local _item_0 = _obj_2[_index_0] _accum_0[_len_0] = _item_0 _len_0 = _len_0 + 1 diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua index 7a11bac..7c1004b 100644 --- a/spec/outputs/switch.lua +++ b/spec/outputs/switch.lua @@ -740,8 +740,8 @@ do do local _accum_0 = { } local _len_0 = 1 - local _max_0 = -3 - for _index_0 = 1, _max_0 < 0 and #clientData + _max_0 + 1 or _max_0 do + local _max_0 = #clientData + -3 + 1 + for _index_0 = 1, _max_0 do local _item_0 = clientData[_index_0] _accum_0[_len_0] = _item_0 _len_0 = _len_0 + 1 diff --git a/spec/outputs/unicode/comprehension.lua b/spec/outputs/unicode/comprehension.lua index 894e78f..92bce69 100644 --- a/spec/outputs/unicode/comprehension.lua +++ b/spec/outputs/unicode/comprehension.lua @@ -243,8 +243,11 @@ end do local _accum_0 = { } local _len_0 = 1 + local _min_0 = 1 + 2 local _max_0 = 3 + 4 - for _index_0 = 1 + 2, _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 do + _min_0 = _min_0 < 0 and #_u5217_u8868 + _min_0 + 1 or _min_0 + _max_0 = _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 + for _index_0 = _min_0, _max_0 do local _u9879_u76ee = _u5217_u8868[_index_0] _accum_0[_len_0] = _u9879_u76ee _len_0 = _len_0 + 1 @@ -254,8 +257,11 @@ end do local _accum_0 = { } local _len_0 = 1 + local _min_0 = _u4f60_u597d() * 4 local _max_0 = 2 - _u4e1c_u897f[4] - for _index_0 = _u4f60_u597d() * 4, _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 do + _min_0 = _min_0 < 0 and #_u5217_u8868 + _min_0 + 1 or _min_0 + _max_0 = _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 + for _index_0 = _min_0, _max_0 do local _u9879_u76ee = _u5217_u8868[_index_0] _accum_0[_len_0] = _u9879_u76ee _len_0 = _len_0 + 1 diff --git a/spec/outputs/unicode/lists.lua b/spec/outputs/unicode/lists.lua index a3c329b..3bf6f50 100644 --- a/spec/outputs/unicode/lists.lua +++ b/spec/outputs/unicode/lists.lua @@ -229,31 +229,36 @@ _u53d8_u91cfx = { 6, 7 } -local _max_0 = -5 -for _index_0 = 2, _max_0 < 0 and #_u53d8_u91cfx + _max_0 + 1 or _max_0, 2 do +local _max_0 = #_u53d8_u91cfx + -5 + 1 +for _index_0 = 2, _max_0, 2 do local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] _u6253_u5370(_u53d8_u91cfy) end -local _max_1 = 3 -for _index_0 = 1, _max_1 < 0 and #_u53d8_u91cfx + _max_1 + 1 or _max_1 do +for _index_0 = 1, 3 do local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] _u6253_u5370(_u53d8_u91cfy) end -for _index_0 = 2, #_u53d8_u91cfx do +local _max_1 = #_u53d8_u91cfx +for _index_0 = 2, _max_1 do local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] _u6253_u5370(_u53d8_u91cfy) end -for _index_0 = 1, #_u53d8_u91cfx, 2 do +local _max_2 = #_u53d8_u91cfx +for _index_0 = 1, _max_2, 2 do local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] _u6253_u5370(_u53d8_u91cfy) end -for _index_0 = 2, #_u53d8_u91cfx, 2 do +local _max_3 = #_u53d8_u91cfx +for _index_0 = 2, _max_3, 2 do local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] _u6253_u5370(_u53d8_u91cfy) end local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2 -local _max_2 = _u53d8_u91cfb -for _index_0 = _u53d8_u91cfa, _max_2 < 0 and #_u53d8_u91cfx + _max_2 + 1 or _max_2, _u53d8_u91cfc do +local _min_0 = _u53d8_u91cfa +local _max_4 = _u53d8_u91cfb +_min_0 = _min_0 < 0 and #_u53d8_u91cfx + _min_0 + 1 or _min_0 +_max_4 = _max_4 < 0 and #_u53d8_u91cfx + _max_4 + 1 or _max_4 +for _index_0 = _min_0, _max_4, _u53d8_u91cfc do local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] _u6253_u5370(_u53d8_u91cfy) end diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index cbf976f..9f5a41e 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -8180,6 +8180,11 @@ private: } bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { + enum class NumState { + Unknown, + Positive, + Negtive + }; auto x = nameList; str_list temp; str_list vars; @@ -8246,15 +8251,35 @@ private: for (auto item : chainList) { chain->items.push_back(item); } - std::string startValue("1"sv); + std::string startValue; + NumState startStatus = NumState::Unknown; if (auto exp = slice->startValue.as()) { transformExp(exp, temp, ExpUsage::Closure); + if (temp.back().at(0) == '-') { + if (_parser.match(temp.back().substr(1))) { + startStatus = NumState::Negtive; + } + } else { + if (_parser.match(temp.back())) { + startStatus = NumState::Positive; + } + } startValue = std::move(temp.back()); temp.pop_back(); } std::string stopValue; + NumState stopStatus = NumState::Unknown; if (auto exp = slice->stopValue.as()) { transformExp(exp, temp, ExpUsage::Closure); + if (temp.back().at(0) == '-') { + if (_parser.match(temp.back().substr(1))) { + stopStatus = NumState::Negtive; + } + } else { + if (_parser.match(temp.back())) { + stopStatus = NumState::Positive; + } + } stopValue = std::move(temp.back()); temp.pop_back(); } @@ -8276,8 +8301,33 @@ private: transformChainValue(chain, temp, ExpUsage::Closure); _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); } + if (startValue.empty()) { + startValue = "1"s; + startStatus = NumState::Positive; + } + std::string minVar; + if (startStatus != NumState::Positive) { + std::string prefix; + if (!extraScope && !inClosure && needScope) { + extraScope = true; + prefix = indent() + "do"s + nll(x); + pushScope(); + } + minVar = getUnusedName("_min_"sv); + varBefore.push_back(minVar); + if (startStatus == NumState::Negtive) { + _buf << prefix << indent() << "local "sv << minVar << " = "sv << "#"sv << listVar << " + "sv << startValue << " + 1"sv << nll(nameList); + } else { + _buf << prefix << indent() << "local "sv << minVar << " = "sv << startValue << nll(nameList); + } + } + bool defaultStop = false; + if (stopValue.empty()) { + stopValue = "#"s + listVar; + defaultStop = true; + } std::string maxVar; - if (!stopValue.empty()) { + if (stopStatus != NumState::Positive) { std::string prefix; if (!extraScope && !inClosure && needScope) { extraScope = true; @@ -8286,14 +8336,45 @@ private: } maxVar = getUnusedName("_max_"sv); varBefore.push_back(maxVar); - _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); + if (stopStatus == NumState::Negtive) { + _buf << indent() << "local "sv << maxVar << " = "sv << "#"sv << listVar << " + "sv << stopValue << " + 1"sv << nll(nameList); + } else { + _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); + } + } + if (startStatus == NumState::Unknown) { + _buf << indent() << minVar << " = "sv << minVar << " < 0 and #"sv << listVar << " + "sv << minVar << " + 1 or "sv << minVar << nll(nameList); + } + if (!defaultStop && stopStatus == NumState::Unknown) { + _buf << indent() << maxVar << " = "sv << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " + 1 or "sv << maxVar << nll(nameList); } _buf << indent() << "for "sv << indexVar << " = "sv; - _buf << startValue << ", "sv; + if (startValue.empty()) { + _buf << "1"sv; + } else { + switch (startStatus) { + case NumState::Unknown: + case NumState::Negtive: + _buf << minVar; + break; + case NumState::Positive: + _buf << startValue; + break; + } + } + _buf << ", "sv; if (stopValue.empty()) { _buf << "#"sv << listVar; } else { - _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " + 1 or "sv << maxVar; + switch (stopStatus) { + case NumState::Unknown: + case NumState::Negtive: + _buf << maxVar; + break; + case NumState::Positive: + _buf << stopValue; + break; + } } if (!stepValue.empty()) { _buf << ", "sv << stepValue; -- cgit v1.2.3-55-g6feb