From 7e91052f4bab0ea97417b91f7270631120e1b9b2 Mon Sep 17 00:00:00 2001 From: Tom <26638278+tomblind@users.noreply.github.com> Date: Mon, 25 Feb 2019 07:37:10 -0700 Subject: [PATCH 1/2] implemented more math function and value conversions, fixing round in the process --- src/LuaTransformer.ts | 125 ++++++++++++++++++++++++++++++----------- test/unit/math.spec.ts | 6 ++ 2 files changed, 99 insertions(+), 32 deletions(-) diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 1fd4e46ff..1debf5906 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -3123,11 +3123,7 @@ export class LuaTransformer { const ownerType = this.checker.getTypeAtLocation(node.expression.expression); if (ownerType.symbol && ownerType.symbol.escapedName === "Math") { - return tstl.createCallExpression( - this.transformMathExpression(node.expression.name), - this.transformArguments(node.arguments), - node - ); + return this.transformMathCallExpression(node); } if (ownerType.symbol && ownerType.symbol.escapedName === "StringConstructor") { @@ -3320,34 +3316,99 @@ export class LuaTransformer { } // Transpile a Math._ property - public transformMathExpression(identifier: ts.Identifier): tstl.TableIndexExpression { - const translation = { - PI: "pi", - abs: "abs", - acos: "acos", - asin: "asin", - atan: "atan", - ceil: "ceil", - cos: "cos", - exp: "exp", - floor: "floor", - log: "log", - max: "max", - min: "min", - pow: "pow", - random: "random", - round: "round", - sin: "sin", - sqrt: "sqrt", - tan: "tan", - }; + public transformMathExpression(identifier: ts.Identifier): tstl.Expression { + const name = identifier.escapedText as string; + switch (name) { + case "PI": + const property = tstl.createStringLiteral("pi"); + const math = tstl.createIdentifier("math"); + return tstl.createTableIndexExpression(math, property, identifier); + + case "E": + case "LN10": + case "LN2": + case "LOG10E": + case "LOG2E": + case "SQRT1_2": + case "SQRT2": + return tstl.createNumericLiteral(Math[name]); - if (translation[identifier.escapedText as string]) { - const property = tstl.createStringLiteral(translation[identifier.escapedText as string]); - const math = tstl.createIdentifier("math"); - return tstl.createTableIndexExpression(math, property, identifier); - } else { - throw TSTLErrors.UnsupportedProperty("math", identifier.escapedText as string, identifier); + default: + throw TSTLErrors.UnsupportedProperty("math", name, identifier); + } + } + + // Transpile a Math._ property + public transformMathCallExpression(node: ts.CallExpression): tstl.Expression { + const expression = node.expression as ts.PropertyAccessExpression; + const params = this.transformArguments(node.arguments); + const expressionName = expression.name.escapedText as string; + switch (expressionName) { + // math.tan(x / y) + case "atan2": + { + const math = tstl.createIdentifier("math"); + const atan = tstl.createStringLiteral("atan"); + const div = tstl.createBinaryExpression(params[0], params[1], tstl.SyntaxKind.DivisionOperator); + return tstl.createCallExpression(tstl.createTableIndexExpression(math, atan), [div], node); + } + + // (math.log(x) / Math.LNe) + case "log10": + case "log2": + { + const math = tstl.createIdentifier("math"); + const log1 = tstl.createTableIndexExpression(math, tstl.createStringLiteral("log")); + const logCall1 = tstl.createCallExpression(log1, params); + const e = tstl.createNumericLiteral(expressionName === "log10" ? Math.LN10 : Math.LN2); + const div = tstl.createBinaryExpression(logCall1, e, tstl.SyntaxKind.DivisionOperator); + return tstl.createParenthesizedExpression(div, node); + } + + // math.log(1 + x) + case "log1p": + { + const math = tstl.createIdentifier("math"); + const log = tstl.createStringLiteral("log"); + const one = tstl.createNumericLiteral(1); + const add = tstl.createBinaryExpression(one, params[0], tstl.SyntaxKind.AdditionOperator); + return tstl.createCallExpression(tstl.createTableIndexExpression(math, log), [add], node); + } + + // math.floor(x + 0.5) + case "round": + { + const math = tstl.createIdentifier("math"); + const floor = tstl.createStringLiteral("floor"); + const half = tstl.createNumericLiteral(0.5); + const add = tstl.createBinaryExpression(params[0], half, tstl.SyntaxKind.AdditionOperator); + return tstl.createCallExpression(tstl.createTableIndexExpression(math, floor), [add], node); + } + + case "abs": + case "acos": + case "asin": + case "atan": + case "ceil": + case "cos": + case "exp": + case "floor": + case "log": + case "max": + case "min": + case "pow": + case "random": + case "sin": + case "sqrt": + case "tan": + { + const math = tstl.createIdentifier("math"); + const method = tstl.createStringLiteral(expressionName); + return tstl.createCallExpression(tstl.createTableIndexExpression(math, method), params, node); + } + + default: + throw TSTLErrors.UnsupportedProperty("math", name, expression); } } diff --git a/test/unit/math.spec.ts b/test/unit/math.spec.ts index ad7a37169..6a749e173 100644 --- a/test/unit/math.spec.ts +++ b/test/unit/math.spec.ts @@ -8,7 +8,13 @@ export class MathTests { @TestCase("Math.cos()", "math.cos();") @TestCase("Math.sin()", "math.sin();") @TestCase("Math.min()", "math.min();") + @TestCase("Math.atan2(2, 3)", "math.atan(2 / 3);") + @TestCase("Math.log2(3)", `(math.log(3) / ${Math.LN2});`) + @TestCase("Math.log10(3)", `(math.log(3) / ${Math.LN10});`) + @TestCase("Math.log1p(3)", "math.log(1 + 3);") + @TestCase("Math.round(3.3)", "math.floor(3.3 + 0.5);") @TestCase("Math.PI", "math.pi;") + @TestCase("Math.E", `${Math.E};`) @Test("Math") public math(inp: string, expected: string): void { // Transpile From 560885b7cab474972a90cf4571b4b6e5de20001c Mon Sep 17 00:00:00 2001 From: Tom <26638278+tomblind@users.noreply.github.com> Date: Mon, 25 Feb 2019 13:48:38 -0700 Subject: [PATCH 2/2] math constants: added original node and tests --- src/LuaTransformer.ts | 2 +- test/unit/math.spec.ts | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 1debf5906..7676bf2ff 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -3331,7 +3331,7 @@ export class LuaTransformer { case "LOG2E": case "SQRT1_2": case "SQRT2": - return tstl.createNumericLiteral(Math[name]); + return tstl.createNumericLiteral(Math[name], identifier); default: throw TSTLErrors.UnsupportedProperty("math", name, identifier); diff --git a/test/unit/math.spec.ts b/test/unit/math.spec.ts index 6a749e173..24652e07f 100644 --- a/test/unit/math.spec.ts +++ b/test/unit/math.spec.ts @@ -14,7 +14,6 @@ export class MathTests { @TestCase("Math.log1p(3)", "math.log(1 + 3);") @TestCase("Math.round(3.3)", "math.floor(3.3 + 0.5);") @TestCase("Math.PI", "math.pi;") - @TestCase("Math.E", `${Math.E};`) @Test("Math") public math(inp: string, expected: string): void { // Transpile @@ -24,6 +23,20 @@ export class MathTests { Expect(lua).toBe(expected); } + @TestCase("E") + @TestCase("LN10") + @TestCase("LN2") + @TestCase("LOG10E") + @TestCase("LOG2E") + @TestCase("SQRT1_2") + @TestCase("SQRT2") + @Test("Math constant") + public mathConstant(constant: string): void { + const epsilon = 0.000001; + const code = `return Math.abs(Math.${constant} - ${Math[constant]}) <= ${epsilon}`; + Expect(util.transpileAndExecute(code)).toBe(true); + } + @TestCase("++x", "x=4;y=6") @TestCase("x++", "x=4;y=6") @TestCase("--x", "x=2;y=6")