Skip to content

Commit 7fc3b28

Browse files
committed
Merge branch 'master' into feature/bundling-v2
# Conflicts: # src/utils.ts
2 parents f807b79 + c7b3810 commit 7fc3b28

File tree

7 files changed

+106
-2
lines changed

7 files changed

+106
-2
lines changed

src/LuaLib.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export enum LuaLibFeature {
4040
Number = "Number",
4141
NumberIsFinite = "NumberIsFinite",
4242
NumberIsNaN = "NumberIsNaN",
43+
NumberToString = "NumberToString",
4344
ObjectAssign = "ObjectAssign",
4445
ObjectEntries = "ObjectEntries",
4546
ObjectFromEntries = "ObjectFromEntries",

src/LuaTransformer.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4295,7 +4295,7 @@ export class LuaTransformer {
42954295
}
42964296

42974297
if (tsHelper.isStandardLibraryType(ownerType, "NumberConstructor", this.program)) {
4298-
return this.transformNumberCallExpression(node);
4298+
return this.transformNumberExpression(node);
42994299
}
43004300

43014301
const classDecorators = tsHelper.getCustomDecorators(ownerType, this.checker);
@@ -4308,6 +4308,10 @@ export class LuaTransformer {
43084308
return this.transformStringCallExpression(node);
43094309
}
43104310

4311+
if (tsHelper.isNumberType(ownerType, this.checker, this.program)) {
4312+
return this.transformNumberCallExpression(node);
4313+
}
4314+
43114315
// if ownerType is a array, use only supported functions
43124316
if (tsHelper.isExplicitArrayType(ownerType, this.checker, this.program)) {
43134317
return this.transformArrayCallExpression(node);
@@ -4883,6 +4887,23 @@ export class LuaTransformer {
48834887
);
48844888
}
48854889

4890+
protected transformNumberCallExpression(node: ts.CallExpression): tstl.Expression {
4891+
const expression = node.expression as ts.PropertyAccessExpression;
4892+
const signature = this.checker.getResolvedSignature(node);
4893+
const params = this.transformArguments(node.arguments, signature);
4894+
const caller = this.transformExpression(expression.expression);
4895+
4896+
const expressionName = expression.name.text;
4897+
switch (expressionName) {
4898+
case "toString":
4899+
return params.length === 0
4900+
? tstl.createCallExpression(tstl.createIdentifier("tostring"), [caller], node)
4901+
: this.transformLuaLibFunction(LuaLibFeature.NumberToString, node, caller, ...params);
4902+
default:
4903+
throw TSTLErrors.UnsupportedProperty("number", expressionName, node);
4904+
}
4905+
}
4906+
48864907
// Transpile a String._ property
48874908
protected transformStringExpression(identifier: ts.Identifier): ExpressionVisitResult {
48884909
const identifierString = identifier.text;
@@ -5015,7 +5036,7 @@ export class LuaTransformer {
50155036
}
50165037

50175038
// Transpile a Number._ property
5018-
protected transformNumberCallExpression(expression: ts.CallExpression): tstl.CallExpression {
5039+
protected transformNumberExpression(expression: ts.CallExpression): tstl.CallExpression {
50195040
const method = expression.expression as ts.PropertyAccessExpression;
50205041
const parameters = this.transformArguments(expression.arguments);
50215042
const methodName = method.name.text;

src/lualib/NumberToString.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// tslint:disable-next-line: variable-name
2+
const ____radixChars = "0123456789abcdefghijklmnopqrstuvwxyz";
3+
4+
// https://www.ecma-international.org/ecma-262/10.0/index.html#sec-number.prototype.tostring
5+
function __TS__NumberToString(this: number, radix?: number): string {
6+
if (radix === undefined || radix === 10 || this === Infinity || this === -Infinity || this !== this) {
7+
return this.toString();
8+
}
9+
10+
radix = Math.floor(radix);
11+
if (radix < 2 || radix > 36) {
12+
// tslint:disable-next-line: no-string-throw
13+
throw "toString() radix argument must be between 2 and 36";
14+
}
15+
16+
let [integer, fraction] = math.modf(Math.abs(this));
17+
18+
let result = "";
19+
if (radix === 8) {
20+
result = string.format("%o", integer);
21+
} else if (radix === 16) {
22+
result = string.format("%x", integer);
23+
} else {
24+
do {
25+
result = ____radixChars[integer % radix] + result;
26+
integer = Math.floor(integer / radix);
27+
} while (integer !== 0);
28+
}
29+
30+
// https://github.com/v8/v8/blob/f78e8d43c224847fa56b3220a90be250fc0f0d6e/src/numbers/conversions.cc#L1221
31+
if (fraction !== 0) {
32+
result += ".";
33+
let delta = 1e-16;
34+
do {
35+
fraction *= radix;
36+
delta *= radix;
37+
const digit = Math.floor(fraction);
38+
result += ____radixChars[digit];
39+
fraction -= digit;
40+
// TODO: Round to even
41+
} while (fraction >= delta);
42+
}
43+
44+
if (this < 0) {
45+
result = "-" + result;
46+
}
47+
48+
return result;
49+
}

src/lualib/declarations/math.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/** @noSelf */
2+
declare namespace math {
3+
/** @tupleReturn */
4+
function modf(x: number): [number, number];
5+
}

src/lualib/declarations/string.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ declare namespace string {
88
n?: number
99
): [string, number];
1010
function sub(s: string, i: number, j?: number): string;
11+
function format(formatstring: string, ...args: any[]): string;
1112
}

src/utils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,18 @@ export function formatPathToLuaPath(filePath: string): string {
1111
filePath = filePath.replace(/\.\\/g, "").replace(/\\/g, ".");
1212
}
1313
return filePath.replace(/\.\//g, "").replace(/\//g, ".");
14+
15+
export function flatMap<T, U>(array: readonly T[], callback: (value: T, index: number) => U | readonly U[]): U[] {
16+
const result: U[] = [];
17+
18+
for (const [index, value] of array.entries()) {
19+
const mappedValue = callback(value, index);
20+
if (Array.isArray(mappedValue)) {
21+
result.push(...mappedValue);
22+
} else {
23+
result[result.length] = mappedValue as U;
24+
}
25+
}
26+
27+
return result;
1428
}

test/unit/builtins/numbers.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { flatMap } from "../../../src/utils";
12
import * as util from "../../util";
23

34
test.each([
@@ -48,6 +49,18 @@ describe("Number", () => {
4849
});
4950
});
5051

52+
const toStringRadixes = [undefined, 10, 2, 8, 9, 16, 17, 36, 36.9];
53+
const toStringValues = [-1, 0, 1, 1.5, 1024, 1.2];
54+
const toStringPairs = flatMap(toStringValues, value => toStringRadixes.map(radix => [value, radix] as const));
55+
56+
test.each(toStringPairs)("(%p).toString(%p)", (value, radix) => {
57+
util.testExpressionTemplate`(${value}).toString(${radix})`.expectToMatchJsResult();
58+
});
59+
60+
test.each([NaN, Infinity, -Infinity])("%p.toString(2)", value => {
61+
util.testExpressionTemplate`(${value}).toString(2)`.expectToMatchJsResult();
62+
});
63+
5164
test.each(cases)("isNaN(%p)", value => {
5265
util.testExpressionTemplate`isNaN(${value} as any)`.expectToMatchJsResult();
5366
});

0 commit comments

Comments
 (0)