From c648c5fd937a78f61a4a352901c9a04b4c7e648d Mon Sep 17 00:00:00 2001 From: Perryvw Date: Mon, 26 Mar 2018 20:55:46 +0200 Subject: [PATCH 1/2] Added support for default parameter values --- src/Transpiler.ts | 21 ++++++- .../lua/classMethodDefaultParameters.lua | 14 +++++ .../ts/classMethodDefaultParameters.ts | 5 ++ test/unit/expressions.spec.ts | 58 ++++++++++++++++--- 4 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 test/translation/lua/classMethodDefaultParameters.lua create mode 100644 test/translation/ts/classMethodDefaultParameters.ts diff --git a/src/Transpiler.ts b/src/Transpiler.ts index 349fdadca..14644ca20 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -1186,10 +1186,14 @@ export class LuaTranspiler { paramNames.push((param.name as ts.Identifier).escapedText as string); }); + // Parameters with default values + const defaultValueParams = node.parameters.filter((declaration) => declaration.initializer !== undefined); + // Build function header result += this.indent + `function ${callPath}${methodName}(${paramNames.join(",")})\n`; this.pushIndent(); + result += this.transpileParameterDefaultValues(defaultValueParams); result += this.transpileBlock(body); this.popIndent(); @@ -1370,9 +1374,12 @@ export class LuaTranspiler { paramNames.push((param.name as ts.Identifier).escapedText as string); }); - if (ts.isBlock(node.body)) { + const defaultValueParams = node.parameters.filter((declaration) => declaration.initializer !== undefined); + + if (ts.isBlock(node.body) || defaultValueParams.length > 0) { let result = `function(${paramNames.join(",")})\n`; this.pushIndent(); + result += this.transpileParameterDefaultValues(defaultValueParams); result += this.transpileBlock(node.body); this.popIndent(); return result + this.indent + "end\n"; @@ -1380,4 +1387,16 @@ export class LuaTranspiler { return `function(${paramNames.join(",")}) return ` + this.transpileExpression(node.body) + " end"; } } + + public transpileParameterDefaultValues(params: ts.ParameterDeclaration[]): string { + let result = ""; + + params.filter((declaration) => declaration.initializer !== undefined).forEach((declaration) => { + const paramName = (declaration.name as ts.Identifier).escapedText; + const paramValue = this.transpileExpression(declaration.initializer); + result += this.indent + `if ${paramName}==nil then ${paramName}=${paramValue} end\n`; + }); + + return result; + } } diff --git a/test/translation/lua/classMethodDefaultParameters.lua b/test/translation/lua/classMethodDefaultParameters.lua new file mode 100644 index 000000000..0b9768a31 --- /dev/null +++ b/test/translation/lua/classMethodDefaultParameters.lua @@ -0,0 +1,14 @@ +MyClass = MyClass or {} +MyClass.__index = MyClass +function MyClass.new(construct, ...) + local instance = setmetatable({}, MyClass) + if construct and MyClass.constructor then MyClass.constructor(instance, ...) end + return instance +end +function MyClass.constructor(self) +end +function MyClass.MyMethod(self,a,b) + if a==nil then a=3 end + if b==nil then b=5 end + return a+b +end diff --git a/test/translation/ts/classMethodDefaultParameters.ts b/test/translation/ts/classMethodDefaultParameters.ts new file mode 100644 index 000000000..fc157750f --- /dev/null +++ b/test/translation/ts/classMethodDefaultParameters.ts @@ -0,0 +1,5 @@ +class MyClass { + public MyMethod(a: number = 3, b: number = 5) { + return a + b; + } +} diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index b69b16076..1b3d7f8d0 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -1,4 +1,4 @@ -import { Expect, Test, TestCase } from "alsatian"; +import { Expect, Test, TestCase, FocusTest } from "alsatian"; import * as ts from "typescript"; import * as util from "../src/util"; @@ -27,7 +27,6 @@ export class ExpressionTests { }).toThrowError(Error, expectedError); } - @TestCase("1+1", "1+1") @TestCase("1-1", "1-1") @TestCase("1*1", "1*1") @@ -93,7 +92,7 @@ export class ExpressionTests { @TestCase("a>>>=b", "a=bit.rshift(a,b)") @Test("Bitop [JIT]") public bitOperatorOverrideJIT(input: string, lua: string) { - Expect(util.transpileString(input, { luaTarget: 'JIT', dontRequireLuaLib: true })).toBe(lua); + Expect(util.transpileString(input, { luaTarget: "JIT", dontRequireLuaLib: true })).toBe(lua); } @TestCase("a&b", "a&b") @@ -108,10 +107,9 @@ export class ExpressionTests { @TestCase("a>>>=b", "a=a>>>b") @Test("Bitop [5.3]") public bitOperatorOverride53(input: string, lua: string) { - Expect(util.transpileString(input, { luaTarget: '5.3', dontRequireLuaLib: true })).toBe(lua); + Expect(util.transpileString(input, { luaTarget: "5.3", dontRequireLuaLib: true })).toBe(lua); } - @TestCase("1+1", "1+1") @TestCase("-1+1", "-1+1") @TestCase("1*30+4", "(1*30)+4") @@ -130,7 +128,7 @@ export class ExpressionTests { } @Test("Arrow Function Expression") - public arrowFunctionExpression(input: string) { + public arrowFunctionExpression() { // Transpile const lua = util.transpileString(`let add = (a, b) => a+b; return add(1,2);`); @@ -141,8 +139,31 @@ export class ExpressionTests { Expect(result).toBe(3); } + @TestCase([]) + @TestCase([5]) + @TestCase([1, 2]) + @Test("Arrow Default Values") + public arrowFunctionDefaultValues(inp: number[]) { + // Default value is 3 for v1 + const v1 = inp.length > 0 ? inp[0] : 3; + // Default value is 4 for v2 + const v2 = inp.length > 1 ? inp[1] : 4; + + const callArgs = inp.join(","); + + // Transpile + const lua = util.transpileString(`let add = (a: number = 3, b: number = 4) => { return a+b; }` + + `return add(${callArgs});`); + + // Execute + const result = util.executeLua(lua); + + // Assert + Expect(result).toBe(v1 + v2); + } + @Test("Function Expression") - public functionExpression(input: string) { + public functionExpression() { // Transpile const lua = util.transpileString(`let add = function(a, b) {return a+b}; return add(1,2);`); @@ -152,4 +173,27 @@ export class ExpressionTests { // Assert Expect(result).toBe(3); } + + @TestCase([], 7) + @TestCase([5], 9) + @TestCase([1, 2], 3) + @Test("Arrow Default Values") + public functionExpressionDefaultValues(inp: number[]) { + // Default value is 3 for v1 + const v1 = inp.length > 0 ? inp[0] : 3; + // Default value is 4 for v2 + const v2 = inp.length > 1 ? inp[1] : 4; + + const callArgs = inp.join(","); + + // Transpile + const lua = util.transpileString(`let add = function(a: number = 3, b: number = 4) { return a+b; }` + + `return add(${callArgs});`); + + // Execute + const result = util.executeLua(lua); + + // Assert + Expect(result).toBe(v1 + v2); + } } From 25b414315c94d01492439c33700f00a136ea8468 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Mon, 26 Mar 2018 22:26:25 +0200 Subject: [PATCH 2/2] removed unused import --- test/unit/expressions.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/expressions.spec.ts b/test/unit/expressions.spec.ts index 1b3d7f8d0..47a164160 100644 --- a/test/unit/expressions.spec.ts +++ b/test/unit/expressions.spec.ts @@ -1,4 +1,4 @@ -import { Expect, Test, TestCase, FocusTest } from "alsatian"; +import { Expect, Test, TestCase } from "alsatian"; import * as ts from "typescript"; import * as util from "../src/util";