Skip to content
5 changes: 3 additions & 2 deletions src/transformation/builtins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { transformConsoleCall } from "./console";
import { transformFunctionPrototypeCall, transformFunctionProperty } from "./function";
import { tryTransformBuiltinGlobalCall } from "./global";
import { transformMathCall, transformMathProperty } from "./math";
import { transformNumberConstructorCall, transformNumberPrototypeCall } from "./number";
import { transformNumberConstructorCall, transformNumberPrototypeCall, transformNumberProperty } from "./number";
import { transformObjectConstructorCall, tryTransformObjectPrototypeCall } from "./object";
import { transformPromiseConstructorCall } from "./promise";
import { transformStringConstructorCall, transformStringProperty, transformStringPrototypeCall } from "./string";
Expand All @@ -27,6 +27,8 @@ export function transformBuiltinPropertyAccessExpression(

if (ts.isIdentifier(node.expression) && isStandardLibraryType(context, ownerType, undefined)) {
switch (ownerType.symbol.name) {
case "NumberConstructor":
return transformNumberProperty(context, node);
case "Math":
return transformMathProperty(context, node);
case "SymbolConstructor":
Expand Down Expand Up @@ -162,7 +164,6 @@ export function transformBuiltinIdentifierExpression(
const huge = lua.createStringLiteral("huge");
return lua.createTableIndexExpression(math, huge, node);
}

case "globalThis":
return lua.createIdentifier("_G", node, getIdentifierSymbolId(context, node, symbol), "globalThis");
}
Expand Down
83 changes: 83 additions & 0 deletions src/transformation/builtins/number.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import ts = require("typescript");
import * as lua from "../../LuaAST";
import { createNaN } from "../utils/lua-ast";
import { TransformationContext } from "../context";
import { unsupportedProperty } from "../utils/diagnostics";
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
import { transformArguments } from "../visitors/call";
import { LuaTarget } from "../../CompilerOptions";

export function transformNumberPrototypeCall(
context: TransformationContext,
Expand All @@ -27,6 +29,87 @@ export function transformNumberPrototypeCall(
}
}

export function transformNumberProperty(
context: TransformationContext,
node: ts.PropertyAccessExpression
): lua.Expression | undefined {
const name = node.name.text;

/*
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.
Most of them should be fairly straight forward base on their name(s) though.
*/

switch (name) {
case "POSITIVE_INFINITY":
if (context.luaTarget === LuaTarget.Lua50) {
const one = lua.createNumericLiteral(1);
const zero = lua.createNumericLiteral(0);
return lua.createBinaryExpression(one, zero, lua.SyntaxKind.DivisionOperator);
} else {
const math = lua.createIdentifier("math");
const huge = lua.createStringLiteral("huge");
return lua.createTableIndexExpression(math, huge, node);
}
case "NEGATIVE_INFINITY":
if (context.luaTarget === LuaTarget.Lua50) {
const one = lua.createNumericLiteral(1);
const zero = lua.createNumericLiteral(0);
return lua.createUnaryExpression(
lua.createBinaryExpression(one, zero, lua.SyntaxKind.DivisionOperator),
lua.SyntaxKind.NegationOperator
);
} else {
const math = lua.createIdentifier("math");
const huge = lua.createStringLiteral("huge");
return lua.createUnaryExpression(
lua.createTableIndexExpression(math, huge, node),
lua.SyntaxKind.NegationOperator
);
}
case "NaN":
return createNaN(node);
case "EPSILON":
return lua.createBinaryExpression(
lua.createNumericLiteral(2),
lua.createNumericLiteral(-52),
lua.SyntaxKind.PowerOperator,
node
);
case "MIN_VALUE":
return lua.createBinaryExpression(
lua.createNumericLiteral(-2),
lua.createNumericLiteral(1074),
lua.SyntaxKind.PowerOperator,
node
);
case "MIN_SAFE_INTEGER":
return lua.createBinaryExpression(
lua.createNumericLiteral(-2),
lua.createNumericLiteral(1074),
lua.SyntaxKind.PowerOperator,
node
);
case "MAX_SAFE_INTEGER":
return lua.createBinaryExpression(
lua.createNumericLiteral(2),
lua.createNumericLiteral(1024),
lua.SyntaxKind.PowerOperator,
node
);
case "MAX_VALUE":
return lua.createBinaryExpression(
lua.createNumericLiteral(2),
lua.createNumericLiteral(1024),
lua.SyntaxKind.PowerOperator,
node
);

default:
context.diagnostics.push(unsupportedProperty(node.name, "Number", name));
}
}

export function transformNumberConstructorCall(
context: TransformationContext,
node: ts.CallExpression,
Expand Down
14 changes: 14 additions & 0 deletions test/unit/builtins/numbers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,17 @@ test.each(["42", "undefined"])("prototype call on nullable number (%p)", value =
.setOptions({ strictNullChecks: true })
.expectToMatchJsResult();
});

test.each([
"Number.NEGATIVE_INFINITY <= Number.MIN_VALUE",
"Number.MIN_VALUE <= Number.MIN_SAFE_INTEGER",

"Number.MAX_SAFE_INTEGER <= Number.MAX_VALUE",
"Number.MAX_VALUE <= Number.POSITIVE_INFINITY",
"Number.MIN_SAFE_INTEGER < 0",

"0 < Number.EPSILON",
"Number.EPSILON < Number.MAX_SAFE_INTEGER",
])("Numer constants have correct relative sizes (%p)", comparison => {
util.testExpression(comparison).expectToEqual(true);
});