Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING CHANGE: Unify Math & Mathf. Make every method in Math polymorphic #2335

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
12 changes: 6 additions & 6 deletions src/common.ts
Expand Up @@ -216,9 +216,7 @@ export namespace CommonNames {
export const ArrayBufferView = "ArrayBufferView";
export const ArrayBuffer = "ArrayBuffer";
export const Math = "Math";
export const Mathf = "Mathf";
export const NativeMath = "NativeMath";
export const NativeMathf = "NativeMathf";
export const Int8Array = "Int8Array";
export const Int16Array = "Int16Array";
export const Int32Array = "Int32Array";
Expand All @@ -236,10 +234,12 @@ export namespace CommonNames {
export const abort = "abort";
export const trace = "trace";
export const seed = "seed";
export const pow = "pow";
export const ipow32 = "ipow32";
export const ipow64 = "ipow64";
export const mod = "mod";
export const fpow32 = "~lib/util/math/pow32";
export const fpow64 = "~lib/util/math/pow64";
export const ipow32 = "~lib/util/math/ipow32";
export const ipow64 = "~lib/util/math/ipow64";
export const fmod32 = "~lib/util/math/mod32";
export const fmod64 = "~lib/util/math/mod64";
export const alloc = "__alloc";
export const realloc = "__realloc";
export const free = "__free";
Expand Down
60 changes: 12 additions & 48 deletions src/compiler.ts
Expand Up @@ -5327,23 +5327,14 @@ export class Compiler extends DiagnosticEmitter {
}
let instance = this.f32PowInstance;
if (!instance) {
let namespace = this.program.lookup(CommonNames.Mathf);
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
reportNode.range, "Mathf"
);
return module.unreachable();
}
let namespaceMembers = namespace.members;
if (!namespaceMembers || !namespaceMembers.has(CommonNames.pow)) {
let prototype = this.program.lookup(CommonNames.fpow32);
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
reportNode.range, "Mathf.pow"
reportNode.range, "pow32"
);
return module.unreachable();
}
let prototype = assert(namespaceMembers.get(CommonNames.pow));
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f32PowInstance = instance = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
}
Expand All @@ -5369,23 +5360,14 @@ export class Compiler extends DiagnosticEmitter {
}
let instance = this.f64PowInstance;
if (!instance) {
let namespace = this.program.lookup(CommonNames.Math);
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
reportNode.range, "Math"
);
return module.unreachable();
}
let namespaceMembers = namespace.members;
if (!namespaceMembers || !namespaceMembers.has(CommonNames.pow)) {
let prototype = this.program.lookup(CommonNames.fpow64);
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
reportNode.range, "Math.pow"
reportNode.range, "pow64"
);
return module.unreachable();
}
let prototype = assert(namespaceMembers.get(CommonNames.pow));
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f64PowInstance = instance = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
}
Expand Down Expand Up @@ -5507,23 +5489,14 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.F32: {
let instance = this.f32ModInstance;
if (!instance) {
let namespace = this.program.lookup(CommonNames.Mathf);
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
reportNode.range, "Mathf"
);
return module.unreachable();
}
let namespaceMembers = namespace.members;
if (!namespaceMembers || !namespaceMembers.has(CommonNames.mod)) {
let prototype = this.program.lookup(CommonNames.fmod32);
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
reportNode.range, "Mathf.mod"
reportNode.range, "mod32"
);
return module.unreachable();
}
let prototype = assert(namespaceMembers.get(CommonNames.mod));
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f32ModInstance = instance = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
}
Expand All @@ -5535,23 +5508,14 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.F64: {
let instance = this.f64ModInstance;
if (!instance) {
let namespace = this.program.lookup(CommonNames.Math);
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
reportNode.range, "Math"
);
return module.unreachable();
}
let namespaceMembers = namespace.members;
if (!namespaceMembers || !namespaceMembers.has(CommonNames.mod)) {
let prototype = this.program.lookup(CommonNames.fmod64);
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
reportNode.range, "Math.mod"
reportNode.range, "mod64"
);
return module.unreachable();
}
let prototype = assert(namespaceMembers.get(CommonNames.mod));
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f64ModInstance = instance = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
}
Expand Down
3 changes: 0 additions & 3 deletions src/program.ts
Expand Up @@ -1401,9 +1401,6 @@ export class Program extends DiagnosticEmitter {
if (!globalAliases.has(CommonNames.Math)) {
globalAliases.set(CommonNames.Math, CommonNames.NativeMath);
}
if (!globalAliases.has(CommonNames.Mathf)) {
globalAliases.set(CommonNames.Mathf, CommonNames.NativeMathf);
}
// TODO: for (let [alias, name] of globalAliases) {
for (let _keys = Map_keys(globalAliases), i = 0, k = _keys.length; i < k; ++i) {
let alias = unchecked(_keys[i]);
Expand Down
142 changes: 70 additions & 72 deletions std/assembly/index.d.ts
Expand Up @@ -2024,128 +2024,122 @@ interface SymbolConstructor {

declare const Symbol: SymbolConstructor;

// prevent infer T as literal
/** @internal */
interface IMath<T> {
type Widen<T> = T extends number ? number : T;

/** @internal */
interface IMath {
/** The base of natural logarithms, e, approximately 2.718. */
readonly E: T;
readonly E: f64;
/** The natural logarithm of 2, approximately 0.693. */
readonly LN2: T;
readonly LN2: f64;
/** The natural logarithm of 10, approximately 2.302. */
readonly LN10: T;
readonly LN10: f64;
/** The base 2 logarithm of e, approximately 1.442. */
readonly LOG2E: T;
readonly LOG2E: f64;
/** The base 10 logarithm of e, approximately 0.434. */
readonly LOG10E: T;
readonly LOG10E: f64;
/** The ratio of the circumference of a circle to its diameter, approximately 3.14159. */
readonly PI: T;
readonly PI: f64;
/** The square root of 1/2, approximately 0.707. */
readonly SQRT1_2: T;
readonly SQRT1_2: f64;
/** The square root of 2, approximately 1.414. */
readonly SQRT2: T;
readonly SQRT2: f64;
/** Returns the absolute value of `x`. */
abs(x: T): T;
abs<T extends Widen<u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>>(x: T): Widen<T>;
/** Returns the arccosine (in radians) of `x`. */
acos(x: T): T;
acos<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the hyperbolic arc-cosine of `x`. */
acosh(x: T): T;
acosh<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the arcsine (in radians) of `x`. */
asin(x: T): T;
asin<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the hyperbolic arcsine of `x`. */
asinh(x: T): T;
asinh<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the arctangent (in radians) of `x`. */
atan(x: T): T;
atan<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the arctangent of the quotient of its arguments. */
atan2(y: T, x: T): T;
atan2<T extends f32 | f64>(y: T, x: T): Widen<T>;
/** Returns the hyperbolic arctangent of `x`. */
atanh(x: T): T;
atanh<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the cube root of `x`. */
cbrt(x: T): T;
cbrt<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the smallest integer greater than or equal to `x`. */
ceil(x: T): T;
/** Returns the number of leading zero bits in the 32-bit binary representation of `x`. */
clz32(x: T): T;
ceil<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(x: T): Widen<T>;
/** @deprecated Returns the number of leading zero bits in the 32-bit binary representation of `x`. */
clz32<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(x: T): Widen<T>;
/** Returns the cosine (in radians) of `x`. */
cos(x: T): T;
cos<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the hyperbolic cosine of `x`. */
cosh(x: T): T;
cosh<T extends f32 | f64>(x: T): Widen<T>;
/** Returns e to the power of `x`. */
exp(x: T): T;
exp<T extends f32 | f64>(x: T): Widen<T>;
/** Returns e to the power of `x`, minus 1. */
expm1(x: T): T;
expm1<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the largest integer less than or equal to `x`. */
floor(x: T): T;
/** Returns the nearest 32-bit single precision float representation of `x`. */
fround(x: T): T;
floor<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(x: T): Widen<T>;
/** @deprecated Returns the nearest 32-bit single precision float representation of `x`. */
fround<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the square root of the sum of squares of its arguments. */
hypot(value1: T, value2: T): T; // TODO: rest
/** Returns the result of the C-like 32-bit multiplication of `a` and `b`. */
imul(a: T, b: T): T;
hypot<T extends f32 | f64>(a: T, b: T): Widen<T>; // TODO: rest
/** @deprecated Returns the result of the C-like 32-bit multiplication of `a` and `b`. */
imul<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(a: T, b: T): Widen<T>;
/** Returns the natural logarithm (base e) of `x`. */
log(x: T): T;
log<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the base 10 logarithm of `x`. */
log10(x: T): T;
log10<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the natural logarithm (base e) of 1 + `x`. */
log1p(x: T): T;
log1p<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the base 2 logarithm of `x`. */
log2(x: T): T;
log2<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the largest-valued number of its arguments. */
max(value1: T, value2: T): T; // TODO: rest
max<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(a: T, b: T): Widen<T>; // TODO: rest
/** Returns the lowest-valued number of its arguments. */
min(value1: T, value2: T): T; // TODO: rest
min<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(a: T, b: T): Widen<T>; // TODO: rest
/** Returns `base` to the power of `exponent`. */
pow(base: T, exponent: T): T;
pow<T extends f32 | f64>(base: T, exponent: T): Widen<T>;
/** Returns a pseudo-random number in the range from 0.0 inclusive up to but not including 1.0. */
random(): T;
random(): f64;
/** Returns the value of `x` rounded to the nearest integer. */
round(x: T): T;
round<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(x: T): Widen<T>;
/** Returns the sign of `x`, indicating whether the number is positive, negative or zero. */
sign(x: T): T;
sign<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(x: T): Widen<T>;
/** Returns whether the sign bit of `x` is set. */
signbit(x: T): bool;
signbit<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(x: T): bool;
/** Returns the sine of `x`. */
sin(x: T): T;
sin<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the hyperbolic sine of `x`. */
sinh(x: T): T;
sinh<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the square root of `x`. */
sqrt(x: T): T;
sqrt<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the tangent of `x`. */
tan(x: T): T;
tan<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the hyperbolic tangent of `x`. */
tanh(x: T): T;
tanh<T extends f32 | f64>(x: T): Widen<T>;
/** Returns the integer part of `x` by removing any fractional digits. */
trunc(x: T): T;
trunc<T extends u8 | u16 | u32 | u64 | i8 | i16 | i32 | i64 | f32 | f64>(x: T): Widen<T>;
}

/** @internal */
interface INativeMath<T> extends IMath<T> {
/** Contains sin value produced after Math/Mathf.sincos */
sincos_sin: T;
/** Contains cos value produced after Math/Mathf.sincos */
sincos_cos: T;
interface INativeMath extends IMath {
/** Contains sin value produced after Math.sincos */
sincos_sin: f64;
/** Contains cos value produced after Math.sincos */
sincos_cos: f64;
/** Seeds the random number generator. */
seedRandom(value: i64): void;
/** Multiplies a floating point `x` by 2 raised to power exp `n`. */
scalbn(x: T, n: i32): T;
/** Returns the floating-point remainder of `x / y` (rounded towards zero). */
mod(x: T, y: T): T;
/** Returns the floating-point remainder of `x / y` (rounded to nearest). */
rem(x: T, y: T): T;
/** Returns sin and cos simultaneously for same angle. Results stored to `sincos_s32/64` and `sincos_c32/64` globals */
sincos(x: T): void;
sincos<T extends f32 | f64>(x: T): void;
/** Returns 2 raised to the given power x. Equivalent to 2 ** x. */
exp2(x: T): T;
exp2<T extends f32 | f64>(x: T): Widen<T>;
}

/** Double precision math imported from JavaScript. */
declare const JSMath: IMath<f64>;
declare const JSMath: IMath;
/** Double precision math implemented natively. */
declare const NativeMath: INativeMath<f64>;
/** Single precision math implemented natively. */
declare const NativeMathf: INativeMath<f32>;
declare const NativeMath: INativeMath;
/** Alias of {@link NativeMath} or {@link JSMath} respectively. Defaults to `NativeMath`. */
declare const Math: IMath<f64>;
/** Alias of {@link NativeMathf} or {@link JSMath} respectively. Defaults to `NativeMathf`. */
declare const Mathf: IMath<f32>;
declare const Math: IMath;

/** Environmental abort function. */
declare function abort(msg?: string | null, fileName?: string | null, lineNumber?: i32, columnNumber?: i32): never;
Expand Down Expand Up @@ -2234,8 +2228,10 @@ interface TypedPropertyDescriptor<T> {

/** Annotates a method as a binary operator overload for the specified `token`. */
declare function operator(token:
"[]" | "[]=" | "{}" | "{}=" | "==" | "!=" | ">" | "<" | "<=" | ">=" |
">>" | ">>>" | "<<" | "&" | "|" | "^" | "+" | "-" | "*" | "**" | "/" | "%"
| "[]" | "[]=" | "{}" | "{}="
| "==" | "!=" | ">" | "<" | "<=" | ">="
| ">>" | ">>>" | "<<" | "&" | "|" | "^"
| "+" | "-" | "*" | "**" | "/" | "%"
): (
target: any,
propertyKey: string,
Expand All @@ -2245,8 +2241,10 @@ declare function operator(token:
declare namespace operator {
/** Annotates a method as a binary operator overload for the specified `token`. */
export function binary(token:
"[]" | "[]=" | "{}" | "{}=" | "==" | "!=" | ">" | "<" | "<=" | ">=" |
">>" | ">>>" | "<<" | "&" | "|" | "^" | "+" | "-" | "*" | "**" | "/" | "%"
| "[]" | "[]=" | "{}" | "{}="
| "==" | "!=" | ">" | "<" | "<=" | ">="
| ">>" | ">>>" | "<<" | "&" | "|" | "^"
| "+" | "-" | "*" | "**" | "/" | "%"
): (
target: any,
propertyKey: string,
Expand Down