Skip to content

Commit c85001e

Browse files
authored
Number static data properties (#1492)
* Basic number literal structure * Setup `POSITIVE_INFINITY` * Better structure for number literals * Setup `NEGATIVE_INFINITY` * Add `NaN` * Setup `EPSILON` * Add `MIN_VALUE` * Setup `MAX_VALUE` * Setup `MAX_SAFE_INTEGER` * Setup `MIN_SAFE_INTEGER` * explenation * use unary expressions * add perry's tests * more correct? * fix failing test * fix tests * final number tests fix
1 parent f19f1e1 commit c85001e

File tree

3 files changed

+100
-2
lines changed

3 files changed

+100
-2
lines changed

src/transformation/builtins/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { transformConsoleCall } from "./console";
1111
import { transformFunctionPrototypeCall, transformFunctionProperty } from "./function";
1212
import { tryTransformBuiltinGlobalCall } from "./global";
1313
import { transformMathCall, transformMathProperty } from "./math";
14-
import { transformNumberConstructorCall, transformNumberPrototypeCall } from "./number";
14+
import { transformNumberConstructorCall, transformNumberPrototypeCall, transformNumberProperty } from "./number";
1515
import { transformObjectConstructorCall, tryTransformObjectPrototypeCall } from "./object";
1616
import { transformPromiseConstructorCall } from "./promise";
1717
import { transformStringConstructorCall, transformStringProperty, transformStringPrototypeCall } from "./string";
@@ -27,6 +27,8 @@ export function transformBuiltinPropertyAccessExpression(
2727

2828
if (ts.isIdentifier(node.expression) && isStandardLibraryType(context, ownerType, undefined)) {
2929
switch (ownerType.symbol.name) {
30+
case "NumberConstructor":
31+
return transformNumberProperty(context, node);
3032
case "Math":
3133
return transformMathProperty(context, node);
3234
case "SymbolConstructor":
@@ -162,7 +164,6 @@ export function transformBuiltinIdentifierExpression(
162164
const huge = lua.createStringLiteral("huge");
163165
return lua.createTableIndexExpression(math, huge, node);
164166
}
165-
166167
case "globalThis":
167168
return lua.createIdentifier("_G", node, getIdentifierSymbolId(context, node, symbol), "globalThis");
168169
}

src/transformation/builtins/number.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import ts = require("typescript");
22
import * as lua from "../../LuaAST";
3+
import { createNaN } from "../utils/lua-ast";
34
import { TransformationContext } from "../context";
45
import { unsupportedProperty } from "../utils/diagnostics";
56
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
67
import { transformArguments } from "../visitors/call";
8+
import { LuaTarget } from "../../CompilerOptions";
79

810
export function transformNumberPrototypeCall(
911
context: TransformationContext,
@@ -27,6 +29,87 @@ export function transformNumberPrototypeCall(
2729
}
2830
}
2931

32+
export function transformNumberProperty(
33+
context: TransformationContext,
34+
node: ts.PropertyAccessExpression
35+
): lua.Expression | undefined {
36+
const name = node.name.text;
37+
38+
/*
39+
Read the docs on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number for further info about what these numbers entail.
40+
Most of them should be fairly straight forward base on their name(s) though.
41+
*/
42+
43+
switch (name) {
44+
case "POSITIVE_INFINITY":
45+
if (context.luaTarget === LuaTarget.Lua50) {
46+
const one = lua.createNumericLiteral(1);
47+
const zero = lua.createNumericLiteral(0);
48+
return lua.createBinaryExpression(one, zero, lua.SyntaxKind.DivisionOperator);
49+
} else {
50+
const math = lua.createIdentifier("math");
51+
const huge = lua.createStringLiteral("huge");
52+
return lua.createTableIndexExpression(math, huge, node);
53+
}
54+
case "NEGATIVE_INFINITY":
55+
if (context.luaTarget === LuaTarget.Lua50) {
56+
const one = lua.createNumericLiteral(1);
57+
const zero = lua.createNumericLiteral(0);
58+
return lua.createUnaryExpression(
59+
lua.createBinaryExpression(one, zero, lua.SyntaxKind.DivisionOperator),
60+
lua.SyntaxKind.NegationOperator
61+
);
62+
} else {
63+
const math = lua.createIdentifier("math");
64+
const huge = lua.createStringLiteral("huge");
65+
return lua.createUnaryExpression(
66+
lua.createTableIndexExpression(math, huge, node),
67+
lua.SyntaxKind.NegationOperator
68+
);
69+
}
70+
case "NaN":
71+
return createNaN(node);
72+
case "EPSILON":
73+
return lua.createBinaryExpression(
74+
lua.createNumericLiteral(2),
75+
lua.createNumericLiteral(-52),
76+
lua.SyntaxKind.PowerOperator,
77+
node
78+
);
79+
case "MIN_VALUE":
80+
return lua.createBinaryExpression(
81+
lua.createNumericLiteral(-2),
82+
lua.createNumericLiteral(1074),
83+
lua.SyntaxKind.PowerOperator,
84+
node
85+
);
86+
case "MIN_SAFE_INTEGER":
87+
return lua.createBinaryExpression(
88+
lua.createNumericLiteral(-2),
89+
lua.createNumericLiteral(1074),
90+
lua.SyntaxKind.PowerOperator,
91+
node
92+
);
93+
case "MAX_SAFE_INTEGER":
94+
return lua.createBinaryExpression(
95+
lua.createNumericLiteral(2),
96+
lua.createNumericLiteral(1024),
97+
lua.SyntaxKind.PowerOperator,
98+
node
99+
);
100+
case "MAX_VALUE":
101+
return lua.createBinaryExpression(
102+
lua.createNumericLiteral(2),
103+
lua.createNumericLiteral(1024),
104+
lua.SyntaxKind.PowerOperator,
105+
node
106+
);
107+
108+
default:
109+
context.diagnostics.push(unsupportedProperty(node.name, "Number", name));
110+
}
111+
}
112+
30113
export function transformNumberConstructorCall(
31114
context: TransformationContext,
32115
node: ts.CallExpression,

test/unit/builtins/numbers.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,17 @@ test.each(["42", "undefined"])("prototype call on nullable number (%p)", value =
206206
.setOptions({ strictNullChecks: true })
207207
.expectToMatchJsResult();
208208
});
209+
210+
test.each([
211+
"Number.NEGATIVE_INFINITY <= Number.MIN_VALUE",
212+
"Number.MIN_VALUE <= Number.MIN_SAFE_INTEGER",
213+
214+
"Number.MAX_SAFE_INTEGER <= Number.MAX_VALUE",
215+
"Number.MAX_VALUE <= Number.POSITIVE_INFINITY",
216+
"Number.MIN_SAFE_INTEGER < 0",
217+
218+
"0 < Number.EPSILON",
219+
"Number.EPSILON < Number.MAX_SAFE_INTEGER",
220+
])("Numer constants have correct relative sizes (%p)", comparison => {
221+
util.testExpression(comparison).expectToEqual(true);
222+
});

0 commit comments

Comments
 (0)