From 258cbcc3f368e9f827100bc95e1fef773e9d93ed Mon Sep 17 00:00:00 2001 From: xiangnan <280145668@qq.com> Date: Wed, 9 Oct 2024 22:05:46 +0800 Subject: [PATCH] feat:special handle multiple return functions. close 5 --- README.md | 34 ++++++++++++++++++++++++++ package.json | 2 +- src/App.vue | 2 +- src/js2lua.mjs | 35 +++++++++++++++++++++++++++ src/jsInit.js | 2 ++ test/multipleReturnForLuaFunction.mjs | 6 +++++ 6 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 test/multipleReturnForLuaFunction.mjs diff --git a/README.md b/README.md index e0cc0b9..359cacb 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ js2lua(`let a = 1`, { importStatementHoisting: true }); * [index0To1](#index0To1) * [keywords](#keywords) * [loop](#loop) +* [multipleReturnForLuaFunction](#multipleReturnForLuaFunction) * [object](#object) * [operator](#operator) * [optionalNullish](#optionalNullish) @@ -662,6 +663,39 @@ do end end +``` +## multipleReturnForLuaFunction +### js +```js +let [ok, res] = pcall(foo) +let [ok2, res2] = xpcall(foo) +let [e1, e2] = unpack(bar) +// comparision +let [ok3, res3] = pcall2(foo) +let [ok4, ...res4] = xpcall(foo) + +``` +### lua +```lua +local ok, res = pcall(foo) +local ok2, res2 = xpcall(foo) +local e1, e2 = unpack(bar) +local ok3, res3 +do + local __tmp = pcall2(foo) + ok3 = __tmp[1] + res3 = __tmp[2] +end +local ok4, res4 +do + local __tmp = xpcall(foo) + ok4 = __tmp[1] + res4 = {} + for __i = 2, #__tmp do + res4[#res4 + 1] = __tmp[__i] + end +end + ``` ## object ### js diff --git a/package.json b/package.json index 59e5d20..b10b240 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xiangnanscu/js2lua", - "version": "0.42.0", + "version": "0.43.0", "type": "module", "description": "Writing LuaJIT with the expressiveness of JavaScript.", "main": "src/js2lua.mjs", diff --git a/src/App.vue b/src/App.vue index 9e6479d..5790f55 100644 --- a/src/App.vue +++ b/src/App.vue @@ -50,7 +50,7 @@ const luacode = computed(() => { return js2lua(jscode.value, selectOptions.value); }); -const jsast = computed(() => js2ast(jscode.value, selectOptions.value)); +const jsast = computed(() => js2ast(jscode.value, selectOptions.value)?.program.body); function copylua() { CopyToClipboard("luacode"); } diff --git a/src/js2lua.mjs b/src/js2lua.mjs index 7e6eef2..f91a4fc 100644 --- a/src/js2lua.mjs +++ b/src/js2lua.mjs @@ -127,6 +127,37 @@ function hasIdentifier(ast, name, depth) { ); return find; } +const multiReturnFunctions = ['pcall', 'xpcall', 'unpack']; +function isMultiReturnAssignment(ast) { + // 检查是否为赋值语句 + if (ast.type !== 'VariableDeclaration' || ast.declarations.length !== 1) { + return false; + } + + const declaration = ast.declarations[0]; + + // 检查左边是否为数组解构形式 + if (declaration.id.type !== 'ArrayPattern') { + return false; + } + + // 检查数组解构的元素是否全部为标识符 + if (!declaration.id.elements.every(element => element && element.type === 'Identifier')) { + return false; + } + + // 检查右边是否为函数调用 + if (declaration.init?.type !== 'CallExpression') { + return false; + } + + // 检查函数名是否为Lua的多返回值内置函数 + + const calleeName = declaration.init.callee.name; + + return multiReturnFunctions.includes(calleeName); +} + function renameThisToCls(ast) { walkAst(ast, (node) => { if (node.type == "ThisExpression") { @@ -441,6 +472,10 @@ function ast2lua(ast, opts = {}) { case "File": return joinAst(ast.program.body, ";\n"); case "VariableDeclaration": { + if (isMultiReturnAssignment(ast)) { + const declare = ast.declarations[0] + return `local ${declare.id.elements.map(_ast2lua).join(", ")} = ${_ast2lua(declare.init)}`; + } const declarePrefix = ast.noPrefix ? "" : "local "; return ast.declarations .map(_ast2lua) diff --git a/src/jsInit.js b/src/jsInit.js index 0a06ab8..eec2841 100644 --- a/src/jsInit.js +++ b/src/jsInit.js @@ -1,3 +1,5 @@ +const { a, b: bAlias, ...rest } = { a: 1, b: 2, c: 3, d: 4 } +const [x, y, ...others] = [1, 2, 3, 4] for (i = 0; i < 10; i = i + 2) { if (i % 2) { continue; diff --git a/test/multipleReturnForLuaFunction.mjs b/test/multipleReturnForLuaFunction.mjs new file mode 100644 index 0000000..d109399 --- /dev/null +++ b/test/multipleReturnForLuaFunction.mjs @@ -0,0 +1,6 @@ +let [ok, res] = pcall(foo) +let [ok2, res2] = xpcall(foo) +let [e1, e2] = unpack(bar) +// comparision +let [ok3, res3] = pcall2(foo) +let [ok4, ...res4] = xpcall(foo)