From fcb480618f162817572947cfed96b1ba0d6c5a44 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 20 Jul 2023 18:25:10 +0800 Subject: fix wrong codes generation for in-expression. --- doc/package.json | 4 +-- spec/inputs/in_expression.yue | 9 ++++- spec/outputs/in_expression.lua | 74 ++++++++++++++++++++++++++++++++++-------- src/yuescript/yue_compiler.cpp | 66 ++++++++++++++++++++++++------------- 4 files changed, 115 insertions(+), 38 deletions(-) diff --git a/doc/package.json b/doc/package.json index 0784500..f9e5ebf 100755 --- a/doc/package.json +++ b/doc/package.json @@ -9,8 +9,8 @@ }, "repository": "https://github.com/pigpigyyy/Yuescript/doc", "scripts": { - "dev": "vuepress dev docs", - "build": "vuepress build docs" + "dev": "export NODE_OPTIONS=--openssl-legacy-provider && vuepress dev docs", + "build": "export NODE_OPTIONS=--openssl-legacy-provider && vuepress build docs" }, "license": "MIT", "devDependencies": { diff --git a/spec/inputs/in_expression.yue b/spec/inputs/in_expression.yue index 4080016..6e923e1 100644 --- a/spec/inputs/in_expression.yue +++ b/spec/inputs/in_expression.yue @@ -39,7 +39,14 @@ do not_exist = item not in list check item in list check item in {1, 2, 3} - check item in {[1]: 1, [2]: 2, [3]: 3} + check item(...) in {[1]: 1, [2]: 2, [3]: 3} + +do + check -> x in tb + check -> x not in tb + local x, tb + check -> return x in tb + check -> x not in tb nil diff --git a/spec/outputs/in_expression.lua b/spec/outputs/in_expression.lua index ccc5fd0..ddba69a 100644 --- a/spec/outputs/in_expression.lua +++ b/spec/outputs/in_expression.lua @@ -66,15 +66,19 @@ do end do local item = get() - local exist = (function() + local exist + do local _check_0 = list + local _find_0 = false for _index_0 = 1, #_check_0 do - if _check_0[_index_0] == item then - return true + local _item_0 = _check_0[_index_0] + if _item_0 == item then + _find_0 = true + break end end - return false - end)() + exist = _find_0 + end check((function() local _check_0 = list for _index_0 = 1, #_check_0 do @@ -92,14 +96,18 @@ do 2, 3 } - local not_exist = not (#list > 0 and (function() + local not_exist + do + local _find_0 = false for _index_0 = 1, #list do - if list[_index_0] == item then - return true + local _item_0 = list[_index_0] + if _item_0 == item then + _find_0 = true + break end end - return false - end)()) + not_exist = not _find_0 + end check((#list > 0 and (function() for _index_0 = 1, #list do if list[_index_0] == item then @@ -109,18 +117,58 @@ do return false end)())) check((1 == item or 2 == item or 3 == item)) - check((function() + check((function(...) local _check_0 = { [1] = 1, [2] = 2, [3] = 3 } + local _val_0 = item(...) for _index_0 = 1, #_check_0 do - if _check_0[_index_0] == item then + if _check_0[_index_0] == _val_0 then return true end end return false - end)()) + end)(...)) +end +do + check(function() + local _check_0 = tb + local _val_0 = x + for _index_0 = 1, #_check_0 do + if _check_0[_index_0] == _val_0 then + return true + end + end + return false + end) + check(function() + local _check_0 = tb + local _val_0 = x + for _index_0 = 1, #_check_0 do + if _check_0[_index_0] == _val_0 then + return false + end + end + return true + end) + local x, tb + check(function() + for _index_0 = 1, #tb do + if tb[_index_0] == x then + return true + end + end + return false + end) + check(function() + for _index_0 = 1, #tb do + if tb[_index_0] == x then + return false + end + end + return true + end) end return nil diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index bb715d2..09da047 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -72,7 +72,7 @@ static std::unordered_set Metamethods = { "close"s // Lua 5.4 }; -const std::string_view version = "0.17.7"sv; +const std::string_view version = "0.17.8"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -1161,6 +1161,9 @@ private: auto unary = static_cast(exp->pipeExprs.back()); BREAK_IF(unary->expos.size() != 1); BREAK_IF(!unary->inExp); + if (unary->inExp->item.is()) { + return unary; + } auto value = static_cast(unary->expos.back()); auto varName = singleVariableFrom(value, false); if (varName.empty() || !isLocal(varName)) { @@ -5416,7 +5419,11 @@ private: _buf << "\tif "sv << itemVar << "=="sv << varName << '\n'; _buf << "\t\t"sv << findVar << "=true\n"sv; _buf << "\t\tbreak\n"sv; - _buf << findVar; + if (unary_exp->inExp->not_) { + _buf << "not "sv << findVar; + } else { + _buf << findVar; + } auto blockStr = clearBuf(); auto checkBlock = toAst(blockStr, inExp); block->statements.dup(checkBlock->statements); @@ -5437,30 +5444,44 @@ private: out.push_back(join(temp)); return; } else { - pushFunctionScope(); - pushAnonVarArg(); - pushScope(); - auto arrayCheck = [&]() { + auto arrayCheck = [&](bool exist) { auto indexVar = getUnusedName("_index_"); _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nll(x); incIndentOffset(); _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nll(x); incIndentOffset(); - _buf << indent() << "return true"sv << nll(x); + _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nll(x); decIndentOffset(); _buf << indent() << "end"sv << nll(x); decIndentOffset(); _buf << indent() << "end"sv << nll(x); - _buf << indent() << "return false"sv << nll(x); + _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nll(x); temp.push_back(clearBuf()); }; - bool useShortCheck = !varName.empty() && !checkVar.empty() && isLocal(checkVar); + bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar); if (useShortCheck) { - arrayCheck(); - temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x)); - popScope(); - temp.push_back(indent() + anonFuncEnd() + ')'); + if (usage == ExpUsage::Return) { + arrayCheck(!unary_exp->inExp->not_); + } else { + pushFunctionScope(); + pushAnonVarArg(); + pushScope(); + arrayCheck(true); + temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x)); + popScope(); + temp.push_back(indent() + anonFuncEnd() + ')'); + if (unary_exp->inExp->not_) { + temp.front().insert(0, "not "s); + } + popAnonVarArg(); + popFunctionScope(); + } } else { + if (usage == ExpUsage::Closure) { + pushFunctionScope(); + pushAnonVarArg(); + pushScope(); + } if (checkVar.empty() || !isLocal(checkVar)) { checkVar = getUnusedName("_check_"sv); auto assignment = assignmentFrom(toAst(checkVar, inExp), inExp, inExp); @@ -5476,15 +5497,16 @@ private: auto assignment = assignmentFrom(assignExp, exp, x); transformAssignment(assignment, temp); } - arrayCheck(); - temp.push_front(anonFuncStart() + nll(x)); - popScope(); - temp.push_back(indent() + anonFuncEnd()); - } - popAnonVarArg(); - popFunctionScope(); - if (unary_exp->inExp->not_) { - temp.front().insert(0, "not "s); + if (usage == ExpUsage::Return) { + arrayCheck(!unary_exp->inExp->not_); + } else { + arrayCheck(!unary_exp->inExp->not_); + temp.push_front(anonFuncStart() + nll(x)); + popScope(); + temp.push_back(indent() + anonFuncEnd()); + popAnonVarArg(); + popFunctionScope(); + } } out.push_back(join(temp)); return; -- cgit v1.2.3-55-g6feb