Skip to content

Commit d8a1898

Browse files
authored
implemented more math function and value conversions (#450)
* implemented more math function and value conversions, fixing round in the process * math constants: added original node and tests
1 parent 2a8846a commit d8a1898

File tree

2 files changed

+112
-32
lines changed

2 files changed

+112
-32
lines changed

src/LuaTransformer.ts

Lines changed: 93 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,11 +3123,7 @@ export class LuaTransformer {
31233123
const ownerType = this.checker.getTypeAtLocation(node.expression.expression);
31243124

31253125
if (ownerType.symbol && ownerType.symbol.escapedName === "Math") {
3126-
return tstl.createCallExpression(
3127-
this.transformMathExpression(node.expression.name),
3128-
this.transformArguments(node.arguments),
3129-
node
3130-
);
3126+
return this.transformMathCallExpression(node);
31313127
}
31323128

31333129
if (ownerType.symbol && ownerType.symbol.escapedName === "StringConstructor") {
@@ -3320,34 +3316,99 @@ export class LuaTransformer {
33203316
}
33213317

33223318
// Transpile a Math._ property
3323-
public transformMathExpression(identifier: ts.Identifier): tstl.TableIndexExpression {
3324-
const translation = {
3325-
PI: "pi",
3326-
abs: "abs",
3327-
acos: "acos",
3328-
asin: "asin",
3329-
atan: "atan",
3330-
ceil: "ceil",
3331-
cos: "cos",
3332-
exp: "exp",
3333-
floor: "floor",
3334-
log: "log",
3335-
max: "max",
3336-
min: "min",
3337-
pow: "pow",
3338-
random: "random",
3339-
round: "round",
3340-
sin: "sin",
3341-
sqrt: "sqrt",
3342-
tan: "tan",
3343-
};
3319+
public transformMathExpression(identifier: ts.Identifier): tstl.Expression {
3320+
const name = identifier.escapedText as string;
3321+
switch (name) {
3322+
case "PI":
3323+
const property = tstl.createStringLiteral("pi");
3324+
const math = tstl.createIdentifier("math");
3325+
return tstl.createTableIndexExpression(math, property, identifier);
3326+
3327+
case "E":
3328+
case "LN10":
3329+
case "LN2":
3330+
case "LOG10E":
3331+
case "LOG2E":
3332+
case "SQRT1_2":
3333+
case "SQRT2":
3334+
return tstl.createNumericLiteral(Math[name], identifier);
33443335

3345-
if (translation[identifier.escapedText as string]) {
3346-
const property = tstl.createStringLiteral(translation[identifier.escapedText as string]);
3347-
const math = tstl.createIdentifier("math");
3348-
return tstl.createTableIndexExpression(math, property, identifier);
3349-
} else {
3350-
throw TSTLErrors.UnsupportedProperty("math", identifier.escapedText as string, identifier);
3336+
default:
3337+
throw TSTLErrors.UnsupportedProperty("math", name, identifier);
3338+
}
3339+
}
3340+
3341+
// Transpile a Math._ property
3342+
public transformMathCallExpression(node: ts.CallExpression): tstl.Expression {
3343+
const expression = node.expression as ts.PropertyAccessExpression;
3344+
const params = this.transformArguments(node.arguments);
3345+
const expressionName = expression.name.escapedText as string;
3346+
switch (expressionName) {
3347+
// math.tan(x / y)
3348+
case "atan2":
3349+
{
3350+
const math = tstl.createIdentifier("math");
3351+
const atan = tstl.createStringLiteral("atan");
3352+
const div = tstl.createBinaryExpression(params[0], params[1], tstl.SyntaxKind.DivisionOperator);
3353+
return tstl.createCallExpression(tstl.createTableIndexExpression(math, atan), [div], node);
3354+
}
3355+
3356+
// (math.log(x) / Math.LNe)
3357+
case "log10":
3358+
case "log2":
3359+
{
3360+
const math = tstl.createIdentifier("math");
3361+
const log1 = tstl.createTableIndexExpression(math, tstl.createStringLiteral("log"));
3362+
const logCall1 = tstl.createCallExpression(log1, params);
3363+
const e = tstl.createNumericLiteral(expressionName === "log10" ? Math.LN10 : Math.LN2);
3364+
const div = tstl.createBinaryExpression(logCall1, e, tstl.SyntaxKind.DivisionOperator);
3365+
return tstl.createParenthesizedExpression(div, node);
3366+
}
3367+
3368+
// math.log(1 + x)
3369+
case "log1p":
3370+
{
3371+
const math = tstl.createIdentifier("math");
3372+
const log = tstl.createStringLiteral("log");
3373+
const one = tstl.createNumericLiteral(1);
3374+
const add = tstl.createBinaryExpression(one, params[0], tstl.SyntaxKind.AdditionOperator);
3375+
return tstl.createCallExpression(tstl.createTableIndexExpression(math, log), [add], node);
3376+
}
3377+
3378+
// math.floor(x + 0.5)
3379+
case "round":
3380+
{
3381+
const math = tstl.createIdentifier("math");
3382+
const floor = tstl.createStringLiteral("floor");
3383+
const half = tstl.createNumericLiteral(0.5);
3384+
const add = tstl.createBinaryExpression(params[0], half, tstl.SyntaxKind.AdditionOperator);
3385+
return tstl.createCallExpression(tstl.createTableIndexExpression(math, floor), [add], node);
3386+
}
3387+
3388+
case "abs":
3389+
case "acos":
3390+
case "asin":
3391+
case "atan":
3392+
case "ceil":
3393+
case "cos":
3394+
case "exp":
3395+
case "floor":
3396+
case "log":
3397+
case "max":
3398+
case "min":
3399+
case "pow":
3400+
case "random":
3401+
case "sin":
3402+
case "sqrt":
3403+
case "tan":
3404+
{
3405+
const math = tstl.createIdentifier("math");
3406+
const method = tstl.createStringLiteral(expressionName);
3407+
return tstl.createCallExpression(tstl.createTableIndexExpression(math, method), params, node);
3408+
}
3409+
3410+
default:
3411+
throw TSTLErrors.UnsupportedProperty("math", name, expression);
33513412
}
33523413
}
33533414

test/unit/math.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ export class MathTests {
88
@TestCase("Math.cos()", "math.cos();")
99
@TestCase("Math.sin()", "math.sin();")
1010
@TestCase("Math.min()", "math.min();")
11+
@TestCase("Math.atan2(2, 3)", "math.atan(2 / 3);")
12+
@TestCase("Math.log2(3)", `(math.log(3) / ${Math.LN2});`)
13+
@TestCase("Math.log10(3)", `(math.log(3) / ${Math.LN10});`)
14+
@TestCase("Math.log1p(3)", "math.log(1 + 3);")
15+
@TestCase("Math.round(3.3)", "math.floor(3.3 + 0.5);")
1116
@TestCase("Math.PI", "math.pi;")
1217
@Test("Math")
1318
public math(inp: string, expected: string): void {
@@ -18,6 +23,20 @@ export class MathTests {
1823
Expect(lua).toBe(expected);
1924
}
2025

26+
@TestCase("E")
27+
@TestCase("LN10")
28+
@TestCase("LN2")
29+
@TestCase("LOG10E")
30+
@TestCase("LOG2E")
31+
@TestCase("SQRT1_2")
32+
@TestCase("SQRT2")
33+
@Test("Math constant")
34+
public mathConstant(constant: string): void {
35+
const epsilon = 0.000001;
36+
const code = `return Math.abs(Math.${constant} - ${Math[constant]}) <= ${epsilon}`;
37+
Expect(util.transpileAndExecute(code)).toBe(true);
38+
}
39+
2140
@TestCase("++x", "x=4;y=6")
2241
@TestCase("x++", "x=4;y=6")
2342
@TestCase("--x", "x=2;y=6")

0 commit comments

Comments
 (0)