diff --git a/src/builtins.ts b/src/builtins.ts index df555860..a824506d 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -153,7 +153,12 @@ export function compileCall( ); return module.createUnreachable(); } - let element = compiler.resolver.resolveExpression(operands[0], compiler.currentFunction, ReportMode.SWALLOW); + let element = compiler.resolver.resolveExpression( + operands[0], + compiler.currentFunction, + Type.void, + ReportMode.SWALLOW + ); return module.createI32(element ? 1 : 0); } case "isConstant": { // isConstant(expression) -> bool diff --git a/src/compiler.ts b/src/compiler.ts index 21337e60..c381c9d6 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -5421,33 +5421,22 @@ export class Compiler extends DiagnosticEmitter { if (thisArg) { let parent = assert(instance.parent); assert(parent.kind == ElementKind.CLASS); - if (getExpressionId(thisArg) == ExpressionId.GetLocal) { - flow.addScopedLocalAlias( - getGetLocalIndex(thisArg), - (parent).type, - "this" - ); - let parentBase = (parent).base; - if (parentBase) { - flow.addScopedLocalAlias( - getGetLocalIndex(thisArg), - parentBase.type, - "super" - ); - } - } else { - let thisLocal = flow.addScopedLocal((parent).type, "this", false); + let thisType = assert(instance.signature.thisType); + let classType = thisType.classReference; + let superType = classType + ? classType.base + ? classType.base.type + : null + : null; + if (getExpressionId(thisArg) == ExpressionId.GetLocal) { // reuse this var + flow.addScopedLocalAlias(getGetLocalIndex(thisArg), thisType, "this"); + if (superType) flow.addScopedLocalAlias(getGetLocalIndex(thisArg), superType, "super"); + } else { // use a temp var + let thisLocal = flow.addScopedLocal(thisType, "this", false); body.push( module.createSetLocal(thisLocal.index, thisArg) ); - let parentBase = (parent).base; - if (parentBase) { - flow.addScopedLocalAlias( - thisLocal.index, - parentBase.type, - "super" - ); - } + if (superType) flow.addScopedLocalAlias(thisLocal.index, superType, "super"); } } var parameterTypes = signature.parameterTypes; @@ -5895,7 +5884,7 @@ export class Compiler extends DiagnosticEmitter { } compileElementAccessExpression(expression: ElementAccessExpression, contextualType: Type): ExpressionRef { - var target = this.resolver.resolveElementAccess(expression, this.currentFunction); // reports + var target = this.resolver.resolveElementAccess(expression, this.currentFunction, contextualType); // reports if (!target) return this.module.createUnreachable(); switch (target.kind) { case ElementKind.CLASS: { @@ -6003,7 +5992,7 @@ export class Compiler extends DiagnosticEmitter { if (currentFunction.is(CommonFlags.INSTANCE)) { let parent = assert(currentFunction.parent); assert(parent.kind == ElementKind.CLASS); - let thisType = (parent).type; + let thisType = assert(currentFunction.signature.thisType); if (currentFunction.is(CommonFlags.CONSTRUCTOR)) { if (!flow.is(FlowFlags.ALLOCATES)) { flow.set(FlowFlags.ALLOCATES); @@ -6194,84 +6183,16 @@ export class Compiler extends DiagnosticEmitter { intValue ); } - switch (contextualType.kind) { - - // compile to contextualType if matching - - case TypeKind.I8: { - if (i64_is_i8(intValue)) return module.createI32(i64_low(intValue)); - break; - } - case TypeKind.U8: { - if (i64_is_u8(intValue)) return module.createI32(i64_low(intValue)); - break; - } - case TypeKind.I16: { - if (i64_is_i16(intValue)) return module.createI32(i64_low(intValue)); - break; - } - case TypeKind.U16: { - if (i64_is_u16(intValue)) return module.createI32(i64_low(intValue)); - break; - } - case TypeKind.I32: { - if (i64_is_i32(intValue)) return module.createI32(i64_low(intValue)); - break; - } - case TypeKind.U32: { - if (i64_is_u32(intValue)) return module.createI32(i64_low(intValue)); - break; - } - case TypeKind.BOOL: { - if (i64_is_bool(intValue)) return module.createI32(i64_low(intValue)); - break; - } - case TypeKind.ISIZE: { - if (!this.options.isWasm64) { - if (i64_is_i32(intValue)) return module.createI32(i64_low(intValue)); - break; - } - return module.createI64(i64_low(intValue), i64_high(intValue)); - } - case TypeKind.USIZE: { - if (!this.options.isWasm64) { - if (i64_is_u32(intValue)) return module.createI32(i64_low(intValue)); - break; - } - return module.createI64(i64_low(intValue), i64_high(intValue)); - } - case TypeKind.I64: - case TypeKind.U64: { - return module.createI64(i64_low(intValue), i64_high(intValue)); - } - case TypeKind.F32: { - if (i64_is_f32(intValue)) return module.createF32(i64_to_f32(intValue)); - break; - } - case TypeKind.F64: { - if (i64_is_f64(intValue)) return module.createF64(i64_to_f64(intValue)); - break; - } - case TypeKind.VOID: { - break; // compiles to best fitting type below, being dropped - } - default: { - assert(false); - return module.createUnreachable(); - } - } - - // otherwise compile to best fitting native type - - if (i64_is_i32(intValue)) { - this.currentType = Type.i32; - return module.createI32(i64_low(intValue)); - } else if (i64_is_u32(intValue)) { - this.currentType = Type.u32; - return module.createI32(i64_low(intValue)); - } else { - this.currentType = Type.i64; - return module.createI64(i64_low(intValue), i64_high(intValue)); + let type = this.resolver.determineIntegerLiteralType(intValue, contextualType); + this.currentType = type; + switch (type.kind) { + case TypeKind.ISIZE: if (!this.options.isWasm64) return module.createI32(i64_low(intValue)); + case TypeKind.I64: return module.createI64(i64_low(intValue), i64_high(intValue)); + case TypeKind.USIZE: if (!this.options.isWasm64) return module.createI32(i64_low(intValue)); + case TypeKind.U64: return module.createI64(i64_low(intValue), i64_high(intValue)); + case TypeKind.F32: return module.createF32(i64_to_f32(intValue)); + case TypeKind.F64: return module.createF64(i64_to_f64(intValue)); + default: return module.createI32(i64_low(intValue)); } } case LiteralKind.STRING: { @@ -6749,7 +6670,7 @@ export class Compiler extends DiagnosticEmitter { ): ExpressionRef { var module = this.module; - var target = this.resolver.resolvePropertyAccess(propertyAccess, this.currentFunction); // reports + var target = this.resolver.resolvePropertyAccess(propertyAccess, this.currentFunction, contextualType); // reports if (!target) return module.createUnreachable(); switch (target.kind) { diff --git a/src/program.ts b/src/program.ts index d8d54d2a..c916acf2 100644 --- a/src/program.ts +++ b/src/program.ts @@ -328,6 +328,8 @@ export class Program extends DiagnosticEmitter { fileLevelExports: Map = new Map(); /** Module-level exports by exported name. */ moduleLevelExports: Map = new Map(); + /** Classes backing basic types like `i32`. */ + basicClasses: Map = new Map(); /** ArrayBuffer instance reference. */ arrayBufferInstance: Class | null = null; @@ -641,6 +643,21 @@ export class Program extends DiagnosticEmitter { } } + // register classes backing basic types + this.registerBasicClass(TypeKind.I8, "I8"); + this.registerBasicClass(TypeKind.I16, "I16"); + this.registerBasicClass(TypeKind.I32, "I32"); + this.registerBasicClass(TypeKind.I64, "I64"); + this.registerBasicClass(TypeKind.ISIZE, "Isize"); + this.registerBasicClass(TypeKind.U8, "U8"); + this.registerBasicClass(TypeKind.U16, "U16"); + this.registerBasicClass(TypeKind.U32, "U32"); + this.registerBasicClass(TypeKind.U64, "U64"); + this.registerBasicClass(TypeKind.USIZE, "Usize"); + this.registerBasicClass(TypeKind.BOOL, "Bool"); + this.registerBasicClass(TypeKind.F32, "F32"); + this.registerBasicClass(TypeKind.F64, "F64"); + // register 'start' { let element = assert(this.elementsLookup.get("start")); @@ -727,6 +744,15 @@ export class Program extends DiagnosticEmitter { } } + private registerBasicClass(typeKind: TypeKind, className: string): void { + if (this.elementsLookup.has(className)) { + let element = assert(this.elementsLookup.get(className)); + assert(element.kind == ElementKind.CLASS_PROTOTYPE); + let classElement = this.resolver.resolveClass(element, null); + if (classElement) this.basicClasses.set(typeKind, classElement); + } + } + /** Sets a constant integer value. */ setConstantInteger(globalName: string, type: Type, value: I64): void { assert(type.is(TypeFlags.INTEGER)); diff --git a/src/resolver.ts b/src/resolver.ts index 1bc2c53f..d023d5b3 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -45,14 +45,18 @@ import { LiteralKind, ParenthesizedExpression, AssertionExpression, - Expression + Expression, + IntegerLiteralExpression, + UnaryPrefixExpression, + UnaryPostfixExpression } from "./ast"; import { Type, Signature, typesToString, - TypeKind + TypeKind, + TypeFlags } from "./types"; import { @@ -65,6 +69,10 @@ import { makeMap } from "./util"; +import { + Token +} from "./tokenizer"; + /** Indicates whether errors are reported or not. */ export enum ReportMode { /** Report errors. */ @@ -83,8 +91,6 @@ export class Resolver extends DiagnosticEmitter { currentThisExpression: Expression | null = null; /** Element expression of the previously resolved element access. */ currentElementExpression : Expression | null = null; - /** Whether the last resolved type has been resolved from a placeholder, i.e. `T`. */ - currentTypeIsPlaceholder: bool = false; /** Constructs the resolver for the specified program. */ constructor(program: Program) { @@ -419,11 +425,12 @@ export class Resolver extends DiagnosticEmitter { resolvePropertyAccess( propertyAccess: PropertyAccessExpression, contextualFunction: Function, + contextualType: Type, reportMode: ReportMode = ReportMode.REPORT ): Element | null { // start by resolving the lhs target (expression before the last dot) var targetExpression = propertyAccess.expression; - var target = this.resolveExpression(targetExpression, contextualFunction, reportMode); // reports + var target = this.resolveExpression(targetExpression, contextualFunction, contextualType, reportMode); // reports if (!target) return null; // at this point we know exactly what the target is, so look up the element within @@ -438,11 +445,16 @@ export class Resolver extends DiagnosticEmitter { assert(type != Type.void); let classReference = type.classReference; if (!classReference) { - this.error( - DiagnosticCode.Property_0_does_not_exist_on_type_1, - propertyAccess.property.range, propertyName, (target).type.toString() - ); - return null; + let basicClasses = this.program.basicClasses; + if (!type.is(TypeFlags.REFERENCE) && basicClasses.has(type.kind)) { + classReference = assert(basicClasses.get(type.kind)); + } else { + this.error( + DiagnosticCode.Property_0_does_not_exist_on_type_1, + propertyAccess.property.range, propertyName, (target).type.toString() + ); + return null; + } } target = classReference; break; @@ -545,10 +557,11 @@ export class Resolver extends DiagnosticEmitter { resolveElementAccess( elementAccess: ElementAccessExpression, contextualFunction: Function, + contextualType: Type, reportMode: ReportMode = ReportMode.REPORT ): Element | null { var targetExpression = elementAccess.expression; - var target = this.resolveExpression(targetExpression, contextualFunction, reportMode); + var target = this.resolveExpression(targetExpression, contextualFunction, contextualType, reportMode); if (!target) return null; switch (target.kind) { case ElementKind.GLOBAL: if (!this.ensureResolvedLazyGlobal(target, reportMode)) return null; @@ -596,9 +609,75 @@ export class Resolver extends DiagnosticEmitter { return null; } + determineIntegerLiteralType( + intValue: I64, + contextualType: Type + ): Type { + + if (!contextualType.is(TypeFlags.REFERENCE)) { + // compile to contextualType if matching + switch (contextualType.kind) { + case TypeKind.I8: { + if (i64_is_i8(intValue)) return Type.i8; + break; + } + case TypeKind.U8: { + if (i64_is_u8(intValue)) return Type.u8; + break; + } + case TypeKind.I16: { + if (i64_is_i16(intValue)) return Type.i16; + break; + } + case TypeKind.U16: { + if (i64_is_u16(intValue)) return Type.u16; + break; + } + case TypeKind.I32: { + if (i64_is_i32(intValue)) return Type.i32; + break; + } + case TypeKind.U32: { + if (i64_is_u32(intValue)) return Type.u32; + break; + } + case TypeKind.BOOL: { + if (i64_is_bool(intValue)) return Type.bool; + break; + } + case TypeKind.ISIZE: { + if (!this.program.options.isWasm64) { + if (i64_is_i32(intValue)) return Type.isize32; + break; + } + return Type.isize64; + } + case TypeKind.USIZE: { + if (!this.program.options.isWasm64) { + if (i64_is_u32(intValue)) return Type.usize32; + break; + } + return Type.usize64; + } + case TypeKind.I64: return Type.i64; + case TypeKind.U64: return Type.u64; + case TypeKind.F32: return Type.f32; + case TypeKind.F64: return Type.f64; + case TypeKind.VOID: break; // best fitting below + default: assert(false); + } + } + + // otherwise compile to best fitting native type + if (i64_is_i32(intValue)) return Type.i32; + if (i64_is_u32(intValue)) return Type.u32; + return Type.i64; + } + resolveExpression( expression: Expression, contextualFunction: Function, + contextualType: Type = Type.void, reportMode: ReportMode = ReportMode.REPORT ): Element | null { while (expression.kind == NodeKind.PARENTHESIZED) { @@ -611,17 +690,80 @@ export class Resolver extends DiagnosticEmitter { contextualFunction.flow.contextualTypeArguments, reportMode ); - if (type) { - let classType = type.classReference; - if (classType) { - this.currentThisExpression = null; - this.currentElementExpression = null; - return classType; + if (!type) return null; + let classType = type.classReference; + if (!classType) return null; + this.currentThisExpression = null; + this.currentElementExpression = null; + return classType; + } + case NodeKind.UNARYPREFIX: { + // TODO: overloads + switch ((expression).operator) { + case Token.MINUS: { + let operand = (expression).operand; + // implicitly negate if an integer literal to distinguish between i32/u32/i64 + if (operand.kind == NodeKind.LITERAL && (operand).literalKind == LiteralKind.INTEGER) { + let type = this.determineIntegerLiteralType( + i64_sub(i64_zero, (operand).value), + contextualType + ); + return assert(this.program.basicClasses.get(type.kind)); + } + return this.resolveExpression( + operand, + contextualFunction, + contextualType, + reportMode + ); } + case Token.PLUS: + case Token.PLUS_PLUS: + case Token.MINUS_MINUS: { + return this.resolveExpression( + (expression).operand, + contextualFunction, + contextualType, + reportMode + ); + } + case Token.EXCLAMATION: { + return assert(this.program.basicClasses.get(TypeKind.BOOL)); + } + case Token.TILDE: { + let resolvedOperand = this.resolveExpression( + (expression).operand, + contextualFunction, + contextualType, + reportMode + ); + if (!resolvedOperand) return null; + throw new Error("not implemented"); // TODO: should all elements have a corresponding type right away? + } + default: assert(false); } return null; } - case NodeKind.BINARY: { // TODO: string concatenation, mostly + case NodeKind.UNARYPOSTFIX: { + // TODO: overloads + switch ((expression).operator) { + case Token.PLUS_PLUS: + case Token.MINUS_MINUS: { + return this.resolveExpression( + (expression).operand, + contextualFunction, + contextualType, + reportMode + ); + } + default: assert(false); + } + return null; + } + case NodeKind.BINARY: { + // TODO: all sorts of unary and binary expressions, which means looking up overloads and + // evaluating their return types, knowing the semantics of different operators etc. + // should probably share that code with the compiler somehow, as it also does exactly this. throw new Error("not implemented"); } case NodeKind.THIS: { // -> Class / ClassPrototype @@ -675,6 +817,27 @@ export class Resolver extends DiagnosticEmitter { } case NodeKind.LITERAL: { switch ((expression).literalKind) { + case LiteralKind.INTEGER: { + return assert( + this.program.basicClasses.get( + this.determineIntegerLiteralType( + (expression).value, + contextualType + ).kind + ) + ); + } + case LiteralKind.FLOAT: { + this.currentThisExpression = expression; + this.currentElementExpression = null; + return assert( + this.program.basicClasses.get( + contextualType == Type.f32 + ? TypeKind.F32 + : TypeKind.F64 + ) + ); + } case LiteralKind.STRING: { this.currentThisExpression = expression; this.currentElementExpression = null; @@ -688,6 +851,7 @@ export class Resolver extends DiagnosticEmitter { return this.resolvePropertyAccess( expression, contextualFunction, + contextualType, reportMode ); } @@ -695,12 +859,13 @@ export class Resolver extends DiagnosticEmitter { return this.resolveElementAccess( expression, contextualFunction, + contextualType, reportMode ); } case NodeKind.CALL: { let targetExpression = (expression).expression; - let target = this.resolveExpression(targetExpression, contextualFunction, reportMode); + let target = this.resolveExpression(targetExpression, contextualFunction, contextualType, reportMode); if (!target) return null; if (target.kind == ElementKind.FUNCTION_PROTOTYPE) { let instance = this.resolveFunctionInclTypeArguments( @@ -800,8 +965,21 @@ export class Resolver extends DiagnosticEmitter { reportMode ); if (!classInstance) return null; - thisType = classInstance.type; + let explicitThisType = signatureNode.explicitThisType; + if (explicitThisType) { + thisType = this.resolveType(explicitThisType, contextualTypeArguments, reportMode); + if (!thisType) return null; + } else { + thisType = classInstance.type; + } contextualTypeArguments.set("this", thisType); + } else { + if (signatureNode.explicitThisType) { + this.error( + DiagnosticCode._this_cannot_be_referenced_in_current_location, + signatureNode.explicitThisType.range + ); // recoverable + } } // resolve signature node diff --git a/std/assembly/builtins.ts b/std/assembly/builtins.ts index 47236c90..06bb6408 100644 --- a/std/assembly/builtins.ts +++ b/std/assembly/builtins.ts @@ -47,16 +47,12 @@ export namespace i8 { export const MIN_VALUE: i8 = -128; export const MAX_VALUE: i8 = 127; - @inline export function parseInt(value: string, radix: i32 = 0): i8 { return parseI32(value, radix) } - @inline export function parseFloat(value: string): i8 { return parseFloat(value) } } @builtin export declare function i16(value: void): i16; export namespace i16 { export const MIN_VALUE: i16 = -32768; export const MAX_VALUE: i16 = 32767; - @inline export function parseInt(value: string, radix: i32 = 0): i16 { return parseI32(value, radix) } - @inline export function parseFloat(value: string): i16 { return parseFloat(value) } } @builtin export declare function i32(value: void): i32; @@ -77,8 +73,6 @@ export namespace i32 { @builtin export declare function store8(offset: usize, value: i32, constantOffset?: usize): void; @builtin export declare function store16(offset: usize, value: i32, constantOffset?: usize): void; @builtin export declare function store(offset: usize, value: i32, constantOffset?: usize): void; - @inline export function parseInt(value: string, radix: i32 = 0): i32 { return parseI32(value, radix) } - @inline export function parseFloat(value: string): i32 { return parseFloat(value) } } @builtin export declare function i64(value: void): i64; @@ -102,8 +96,6 @@ export namespace i64 { @builtin export declare function store16(offset: usize, value: i64, constantOffset?: usize): void; @builtin export declare function store32(offset: usize, value: i64, constantOffset?: usize): void; @builtin export declare function store(offset: usize, value: i64, constantOffset?: usize): void; - @inline export function parseInt(value: string, radix: i32 = 0): i64 { return parseI64(value, radix) } - @inline export function parseFloat(value: string): i64 { return parseFloat(value) } } @builtin export declare function isize(value: void): isize; @@ -114,40 +106,30 @@ export namespace isize { export const MAX_VALUE: isize = sizeof() == sizeof() ? 2147483647 : 9223372036854775807; - @inline export function parseInt(value: string, radix: i32 = 0): isize { return parseI64(value, radix) } - @inline export function parseFloat(value: string): isize { return parseFloat(value) } } @builtin export declare function u8(value: void): u8; export namespace u8 { export const MIN_VALUE: u8 = 0; export const MAX_VALUE: u8 = 255; - @inline export function parseInt(value: string, radix: i32 = 0): u8 { return parseI32(value, radix) } - @inline export function parseFloat(value: string): u8 { return parseFloat(value) } } @builtin export declare function u16(value: void): u16; export namespace u16 { export const MIN_VALUE: u16 = 0; export const MAX_VALUE: u16 = 65535; - @inline export function parseInt(value: string, radix: i32 = 0): u16 { return parseI32(value, radix) } - @inline export function parseFloat(value: string): u16 { return parseFloat(value) } } @builtin export declare function u32(value: void): u32; export namespace u32 { export const MIN_VALUE: u32 = 0; export const MAX_VALUE: u32 = 4294967295; - @inline export function parseInt(value: string, radix: i32 = 0): u32 { return parseI32(value, radix) } - @inline export function parseFloat(value: string): u32 { return parseFloat(value) } } @builtin export declare function u64(value: void): u64; export namespace u64 { export const MIN_VALUE: u64 = 0; export const MAX_VALUE: u64 = 18446744073709551615; - @inline export function parseInt(value: string, radix: i32 = 0): u64 { return parseI64(value, radix) } - @inline export function parseFloat(value: string): u64 { return parseFloat(value) } } @builtin export declare function usize(value: void): usize; @@ -156,8 +138,6 @@ export namespace usize { export const MAX_VALUE: usize = sizeof() == sizeof() ? 4294967295 : 18446744073709551615; - @inline export function parseInt(value: string, radix: i32 = 0): usize { return parseI64(value, radix) } - @inline export function parseFloat(value: string): usize { return parseFloat(value) } } @builtin export declare function bool(value: void): bool; @@ -174,9 +154,6 @@ export namespace f32 { export const MIN_NORMAL_VALUE = reinterpret(0x00800000); // 0x1p-126f export const MIN_SAFE_INTEGER: f32 = -16777215; export const MAX_SAFE_INTEGER: f32 = 16777215; - export const POSITIVE_INFINITY: f32 = Infinity; - export const NEGATIVE_INFINITY: f32 = -Infinity; - export const NaN: f32 = NaN; @builtin export declare function abs(value: f32): f32; @builtin export declare function ceil(value: f32): f32; @builtin export declare function copysign(x: f32, y: f32): f32; @@ -189,12 +166,6 @@ export namespace f32 { @builtin export declare function sqrt(value: f32): f32; @builtin export declare function store(offset: usize, value: f32, constantOffset?: usize): void; @builtin export declare function trunc(value: f32): f32; - @inline export function isNaN(value: f32): bool { return isNaN(value) } - @inline export function isFinite(value: f32): bool { return isFinite(value) } - @inline export function isSafeInteger(value: f32): bool { return abs(value) <= f32.MAX_SAFE_INTEGER && trunc(value) == value } - @inline export function isInteger(value: f32): bool { return isFinite(value) && trunc(value) == value } - @inline export function parseInt(value: string, radix: i32 = 0): f32 { return parseI64(value, radix) } - @inline export function parseFloat(value: string): f32 { return parseFloat(value) } } @builtin export declare function f64(value: void): f64; @@ -205,9 +176,6 @@ export namespace f64 { export const MIN_NORMAL_VALUE = reinterpret(0x0010000000000000); // 0x1p-1022 export const MIN_SAFE_INTEGER: f64 = -9007199254740991; export const MAX_SAFE_INTEGER: f64 = 9007199254740991; - export const POSITIVE_INFINITY: f64 = Infinity; - export const NEGATIVE_INFINITY: f64 = -Infinity; - export const NaN: f64 = NaN; @builtin export declare function abs(value: f64): f64; @builtin export declare function ceil(value: f64): f64; @builtin export declare function copysign(x: f64, y: f64): f64; @@ -220,12 +188,6 @@ export namespace f64 { @builtin export declare function sqrt(value: f64): f64; @builtin export declare function store(offset: usize, value: f64, constantOffset?: usize): void; @builtin export declare function trunc(value: f64): f64; - @inline export function isNaN(value: f64): bool { return isNaN(value) } - @inline export function isFinite(value: f64): bool { return isFinite(value) } - @inline export function isSafeInteger(value: f64): bool { return abs(value) <= f64.MAX_SAFE_INTEGER && trunc(value) == value } - @inline export function isInteger(value: f64): bool { return isFinite(value) && trunc(value) == value } - @inline export function parseInt(value: string, radix: i32 = 0): f64 { return parseI64(value, radix) } - @inline export function parseFloat(value: string): f64 { return parseFloat(value) } } @builtin export declare function start(): void; diff --git a/std/assembly/index.d.ts b/std/assembly/index.d.ts index a2e3a9fb..7ecc015e 100644 --- a/std/assembly/index.d.ts +++ b/std/assembly/index.d.ts @@ -238,7 +238,7 @@ declare namespace i64 { export function parseInt(string: string, radix?: i32): i64; } /** Converts any other numeric value to a 32-bit (in WASM32) respectivel 64-bit (in WASM64) signed integer. */ -declare var isize: i32 | i64; +declare var isize: typeof i32 | typeof i64; /** Converts any other numeric value to an 8-bit unsigned integer. */ declare function u8(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i8; declare namespace u8 { @@ -288,7 +288,7 @@ declare namespace u64 { export function parseInt(string: string, radix?: i32): u64; } /** Converts any other numeric value to a 32-bit (in WASM32) respectivel 64-bit (in WASM64) unsigned integer. */ -declare var usize: u32 | u64; +declare var usize: typeof u32 | typeof u64; /** Converts any other numeric value to a 1-bit unsigned integer. */ declare function bool(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): bool; declare namespace bool { @@ -330,7 +330,7 @@ declare namespace f32 { export function isInteger(value: f32): bool; /** Converts a string to a floating-point number. */ export function parseFloat(string: string): f32; - /** Converts A string to an integer. */ + /** Converts a string to an integer. */ export function parseInt(string: string, radix?: i32): f32; } /** Converts any other numeric value to a 64-bit float. */ @@ -352,22 +352,81 @@ declare namespace f64 { export function load(offset: usize, constantOffset?: usize): f64; /** Stores a 64-bit float to memory. */ export function store(offset: usize, value: f64, constantOffset?: usize): void; - /** Returns a boolean value that indicates whether a value is the reserved value NaN (not a number). */ - export function isNaN(value: f32): bool; - /** Returns true if passed value is finite. */ - export function isFinite(value: f32): bool; - /** Returns true if the value passed is a safe integer. */ - export function isSafeInteger(value: f64): bool; - /** Returns true if the value passed is an integer, false otherwise. */ - export function isInteger(value: f64): bool; - /** Converts a string to a floating-point number. */ - export function parseFloat(string: string): f64; - /** Converts A string to an integer. */ - export function parseInt(string: string, radix?: i32): f64; } /** Macro type evaluating to the underlying native WebAssembly type. */ declare type NATIVE = T; +/** Pseudo-class representing the backing class of integer types. */ +declare class _Integer { + /** Smallest representable value. */ + static readonly MIN_VALUE: number; + /** Largest representable value. */ + static readonly MAX_VALUE: number; + /** Converts a string to an integer of this type. */ + static parseInt(value: string, radix?: number): number; + /** Converts this integer to a string. */ + toString(): string; +} + +/** Pseudo-class representing the backing class of floating-point types. */ +declare class _Float { + /** Difference between 1 and the smallest representable value greater than 1. */ + static readonly EPSILON: f32 | f64; + /** Smallest representable value. */ + static readonly MIN_VALUE: f32 | f64; + /** Largest representable value. */ + static readonly MAX_VALUE: f32 | f64; + /** Smallest safely representable integer value. */ + static readonly MIN_SAFE_INTEGER: f32 | f64; + /** Largest safely representable integer value. */ + static readonly MAX_SAFE_INTEGER: f32 | f64; + /** Value representing positive infinity. */ + static readonly POSITIVE_INFINITY: f32 | f64; + /** Value representing negative infinity. */ + static readonly NEGATIVE_INFINITY: f32 | f64; + /** Value representing 'not a number'. */ + static readonly NaN: f32 | f64; + /** Returns a boolean value that indicates whether a value is the reserved value NaN (not a number). */ + static isNaN(value: f32 | f64): bool; + /** Returns true if passed value is finite. */ + static isFinite(value: f32 | f64): bool; + /** Returns true if the value passed is a safe integer. */ + static isSafeInteger(value: f32 | f64): bool; + /** Returns true if the value passed is an integer, false otherwise. */ + static isInteger(value: f32 | f64): bool; + /** Converts A string to an integer. */ + static parseInt(value: string, radix?: i32): f32 | f64; + /** Converts a string to a floating-point number. */ + static parseFloat(value: string): f32 | f64; + /** Converts this floating-point number to a string. */ + toString(this: f64): string; +} + +/** Backing class of signed 8-bit integers. */ +declare const I8: typeof _Integer; +/** Backing class of signed 16-bit integers. */ +declare const I16: typeof _Integer; +/** Backing class of signed 32-bit integers. */ +declare const I32: typeof _Integer; +/** Backing class of signed 64-bit integers. */ +declare const I64: typeof _Integer; +/** Backing class of signed size integers. */ +declare const Isize: typeof _Integer; +/** Backing class of unsigned 8-bit integers. */ +declare const U8: typeof _Integer; +/** Backing class of unsigned 16-bit integers. */ +declare const U16: typeof _Integer; +/** Backing class of unsigned 32-bit integers. */ +declare const U32: typeof _Integer; +/** Backing class of unsigned 64-bit integers. */ +declare const U64: typeof _Integer; +/** Backing class of unsigned size integers. */ +declare const Usize: typeof _Integer; +/** Backing class of 32-bit floating-point values. */ +declare const F32: typeof _Float; +/** Backing class of 64-bit floating-point values. */ +declare const F64: typeof _Float; + // User-defined diagnostic macros /** Emits a user-defined diagnostic error when encountered. */ diff --git a/std/assembly/iterator.ts b/std/assembly/iterator.ts index fd98ead4..e3df6897 100644 --- a/std/assembly/iterator.ts +++ b/std/assembly/iterator.ts @@ -1,4 +1,35 @@ -// export abstract class Iterator { -// abstract get done(): bool; -// abstract next(): T; -// } +export abstract class Iterable { + // ? +} + +@sealed +export abstract class Iterator { + + // private constructor(iterable: Iterable) { + // } + + // TODO: these need to evaluate the classId at the respective reference in order to obtain the + // next value, i.e. arrays work differently than maps. we'd then have: + // + // ╒═══════════════════ Iterator layout (32-bit) ══════════════════╕ + // 3 2 1 + // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 bits + // ├─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┤ + // │ index │ + // ├─────────────────────────────────────────────────────────┬───┬─┤ + // │ reference │ 0 │D│ + // └─────────────────────────────────────────────────────────┴───┴─┘ + // D: Done flag + + // get value(this: u64): T { + // ? + // } + + // next(this: u64): Iterator { + // ? + // } + + done(this: u64): bool { + return (this & 1); + } +} diff --git a/std/assembly/number.ts b/std/assembly/number.ts new file mode 100644 index 00000000..cfe84746 --- /dev/null +++ b/std/assembly/number.ts @@ -0,0 +1,271 @@ +import { + itoa, + dtoa +} from "./internal/number"; + +import { + isNaN as builtin_isNaN, + isFinite as builtin_isFinite +} from "./builtins"; + +@sealed +export abstract class I8 { + + static readonly MIN_VALUE: i8 = i8.MIN_VALUE; + static readonly MAX_VALUE: i8 = i8.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): i8 { + return parseI32(value, radix); + } + + toString(this: i8): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class I16 { + + static readonly MIN_VALUE: i16 = i16.MIN_VALUE; + static readonly MAX_VALUE: i16 = i16.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): i16 { + return parseI32(value, radix); + } + + toString(this: i16): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class I32 { + + static readonly MIN_VALUE: i32 = i32.MIN_VALUE; + static readonly MAX_VALUE: i32 = i32.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): i32 { + return parseI32(value, radix); + } + + toString(this: i32): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class I64 { + + static readonly MIN_VALUE: i64 = i64.MIN_VALUE; + static readonly MAX_VALUE: i64 = i64.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): i64 { + return parseI64(value, radix); + } + + toString(this: i64): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class Isize { + + static readonly MIN_VALUE: isize = isize.MIN_VALUE; + static readonly MAX_VALUE: isize = isize.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): isize { + return parseI64(value, radix); + } + + toString(this: isize): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class U8 { + + static readonly MIN_VALUE: u8 = u8.MIN_VALUE; + static readonly MAX_VALUE: u8 = u8.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): u8 { + return parseI32(value, radix); + } + + toString(this: u8): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class U16 { + + static readonly MIN_VALUE: u16 = u16.MIN_VALUE; + static readonly MAX_VALUE: u16 = u16.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): u16 { + return parseI32(value, radix); + } + + toString(this: u16): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class U32 { + + static readonly MIN_VALUE: u32 = u32.MIN_VALUE; + static readonly MAX_VALUE: u32 = u32.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): u32 { + return parseI32(value, radix); + } + + toString(this: u32): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class U64 { + + static readonly MIN_VALUE: u64 = u64.MIN_VALUE; + static readonly MAX_VALUE: u64 = u64.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): u64 { + return parseI64(value, radix); + } + + toString(this: u64): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class Usize { + + static readonly MIN_VALUE: usize = usize.MIN_VALUE; + static readonly MAX_VALUE: usize = usize.MAX_VALUE; + + static parseInt(value: string, radix: i32 = 0): usize { + return parseI64(value, radix); + } + + toString(this: usize): String { + // TODO: radix + return itoa(this); + } +} + +@sealed +export abstract class Bool { + + static readonly MIN_VALUE: bool = bool.MIN_VALUE; + static readonly MAX_VALUE: bool = bool.MAX_VALUE; + + toString(this: bool): String { + // TODO: radix? + return this ? "true" : "false"; + } +} + +@sealed +export abstract class Boolean extends Bool {} + +@sealed +export abstract class F32 { + + static readonly EPSILON: f32 = f32.EPSILON; + static readonly MIN_VALUE: f32 = f32.MIN_VALUE; + static readonly MAX_VALUE: f32 = f32.MAX_VALUE; + static readonly MIN_SAFE_INTEGER: f32 = f32.MIN_SAFE_INTEGER; + static readonly MAX_SAFE_INTEGER: f32 = f32.MAX_SAFE_INTEGER; + static readonly POSITIVE_INFINITY: f32 = Infinity; + static readonly NEGATIVE_INFINITY: f32 = -Infinity; + static readonly NaN: f32 = NaN; + + static isNaN(value: f32): bool { + return isNaN(value); + } + + static isFinite(value: f32): bool { + return isFinite(value); + } + + static isSafeInteger(value: f32): bool { + return abs(value) <= f32.MAX_SAFE_INTEGER && trunc(value) == value; + } + + static isInteger(value: f32): bool { + return isFinite(value) && trunc(value) == value; + } + + static parseInt(value: string, radix: i32 = 0): f32 { + return parseI64(value, radix); + } + + static parseFloat(value: string): f32 { + return parseFloat(value); + } + + toString(this: f32): String { + // TODO: radix + return dtoa(this); + } +} + +@sealed +export abstract class F64 { + + static readonly EPSILON: f64 = f64.EPSILON; + static readonly MIN_VALUE: f64 = f64.MIN_VALUE; + static readonly MAX_VALUE: f64 = f64.MAX_VALUE; + static readonly MIN_SAFE_INTEGER: f64 = f64.MIN_SAFE_INTEGER; + static readonly MAX_SAFE_INTEGER: f64 = f64.MAX_SAFE_INTEGER; + static readonly POSITIVE_INFINITY: f64 = Infinity; + static readonly NEGATIVE_INFINITY: f64 = -Infinity; + static readonly NaN: f64 = NaN; + + static isNaN(value: f64): bool { + return builtin_isNaN(value); + } + + static isFinite(value: f64): bool { + return builtin_isFinite(value); + } + + static isSafeInteger(value: f64): bool { + return abs(value) <= f64.MAX_SAFE_INTEGER && trunc(value) == value; + } + + static isInteger(value: f64): bool { + return builtin_isFinite(value) && trunc(value) == value; + } + + static parseInt(value: string, radix: i32 = 0): f64 { + return parseI64(value, radix); + } + + static parseFloat(value: string): f64 { + return parseFloat(value); + } + + toString(this: f64): String { + // TODO: radix + return dtoa(this); + } +} + +@sealed +export abstract class Number extends F64 {} diff --git a/std/portable/index.js b/std/portable/index.js index 7f32ae0e..d8a7a7e0 100644 --- a/std/portable/index.js +++ b/std/portable/index.js @@ -64,10 +64,7 @@ Object.defineProperties( "MAX_VALUE": { value: Math.fround(3.4028235e+38), writable: false }, "MIN_NORMAL_VALUE": { value: Math.fround(1.17549435e-38), writable: false }, "MIN_SAFE_INTEGER": { value: -16777215, writable: false }, - "MAX_SAFE_INTEGER": { value: 16777215, writable: false }, - "POSITIVE_INFINITY": { value: Infinity, writable: false }, - "NEGATIVE_INFINITY": { value: -Infinity, writable: false }, - "NaN": { value: NaN, writable: false } + "MAX_SAFE_INTEGER": { value: 16777215, writable: false } }); Object.defineProperties( @@ -78,10 +75,7 @@ Object.defineProperties( "MAX_VALUE": { value: 1.7976931348623157e+308, writable: false }, "MIN_NORMAL_VALUE": { value: 2.2250738585072014e-308 , writable: false }, "MIN_SAFE_INTEGER": { value: -9007199254740991, writable: false }, - "MAX_SAFE_INTEGER": { value: 9007199254740991, writable: false }, - "POSITIVE_INFINITY": { value: Infinity, writable: false }, - "NEGATIVE_INFINITY": { value: -Infinity, writable: false }, - "NaN": { value: NaN, writable: false } + "MAX_SAFE_INTEGER": { value: 9007199254740991, writable: false } }); globalScope["clz"] = Math.clz32; diff --git a/tests/compiler/builtins.ts b/tests/compiler/builtins.ts index a9bfa2e3..dea322d0 100644 --- a/tests/compiler/builtins.ts +++ b/tests/compiler/builtins.ts @@ -314,27 +314,6 @@ assert(f32.MAX_VALUE == 3.40282347e+38); assert(f32.MIN_SAFE_INTEGER == -16777215); assert(f32.MAX_SAFE_INTEGER == 16777215); assert(f32.EPSILON == 1.19209290e-07); -assert(isNaN(f32.NaN)); -assert(f32.isSafeInteger(f32.MIN_SAFE_INTEGER - 1) == false); -assert(f32.isSafeInteger(f32.MIN_SAFE_INTEGER) == true); -assert(f32.isSafeInteger(+0.0) == true); -assert(f32.isSafeInteger(-0.0) == true); -assert(f32.isSafeInteger(NaN) == false); -assert(f32.isSafeInteger(Infinity) == false); -assert(f32.isSafeInteger(f32.MAX_SAFE_INTEGER) == true); -assert(f32.isSafeInteger(f32.MAX_SAFE_INTEGER + 1) == false); -assert(f32.isSafeInteger(0.5) == false); -assert(f32.isInteger(+0.0) == true); -assert(f32.isInteger(-0.0) == true); -assert(f32.isInteger(NaN) == false); -assert(f32.isInteger(Infinity) == false); -assert(f32.isInteger(f32.EPSILON) == false); -assert(f32.isInteger(+1.0) == true); -assert(f32.isInteger(-1.0) == true); -assert(f32.isInteger(f32.MIN_SAFE_INTEGER) == true); -assert(f32.isInteger(f32.MAX_SAFE_INTEGER) == true); -assert(f32.isInteger(+0.5) == false); -assert(f32.isInteger(-1.5) == false); assert(f64.MIN_NORMAL_VALUE == 2.2250738585072014e-308); assert(f64.MIN_VALUE == 5e-324); @@ -342,27 +321,6 @@ assert(f64.MAX_VALUE == 1.7976931348623157e+308); assert(f64.MIN_SAFE_INTEGER == -9007199254740991); assert(f64.MAX_SAFE_INTEGER == 9007199254740991); assert(f64.EPSILON == 2.2204460492503131e-16); -assert(isNaN(f64.NaN)); -assert(f64.isSafeInteger(f64.MIN_SAFE_INTEGER - 1) == false); -assert(f64.isSafeInteger(f64.MIN_SAFE_INTEGER) == true); -assert(f64.isSafeInteger(+0.0) == true); -assert(f64.isSafeInteger(-0.0) == true); -assert(f64.isSafeInteger(NaN) == false); -assert(f64.isSafeInteger(Infinity) == false); -assert(f64.isSafeInteger(f64.MAX_SAFE_INTEGER) == true); -assert(f64.isSafeInteger(f64.MAX_SAFE_INTEGER + 1) == false); -assert(f64.isSafeInteger(0.5) == false); -assert(f64.isInteger(+0.0) == true); -assert(f64.isInteger(-0.0) == true); -assert(f64.isInteger(NaN) == false); -assert(f64.isInteger(Infinity) == false); -assert(f64.isInteger(f64.EPSILON) == false); -assert(f64.isInteger(+1.0) == true); -assert(f64.isInteger(-1.0) == true); -assert(f64.isInteger(f64.MIN_SAFE_INTEGER) == true); -assert(f64.isInteger(f64.MAX_SAFE_INTEGER) == true); -assert(f64.isInteger(+0.5) == false); -assert(f64.isInteger(-1.5) == false); // inline-assembler diff --git a/tests/compiler/builtins.untouched.wat b/tests/compiler/builtins.untouched.wat index 2f97179d..9615986f 100644 --- a/tests/compiler/builtins.untouched.wat +++ b/tests/compiler/builtins.untouched.wat @@ -44,14 +44,12 @@ (global $~lib/builtins/f32.MIN_SAFE_INTEGER f32 (f32.const -16777215)) (global $~lib/builtins/f32.MAX_SAFE_INTEGER f32 (f32.const 16777215)) (global $~lib/builtins/f32.EPSILON f32 (f32.const 1.1920928955078125e-07)) - (global $~lib/builtins/f32.NaN f32 (f32.const nan:0x400000)) (global $~lib/builtins/f64.MIN_NORMAL_VALUE f64 (f64.const 2.2250738585072014e-308)) (global $~lib/builtins/f64.MIN_VALUE f64 (f64.const 5e-324)) (global $~lib/builtins/f64.MAX_VALUE f64 (f64.const 1797693134862315708145274e284)) (global $~lib/builtins/f64.MIN_SAFE_INTEGER f64 (f64.const -9007199254740991)) (global $~lib/builtins/f64.MAX_SAFE_INTEGER f64 (f64.const 9007199254740991)) (global $~lib/builtins/f64.EPSILON f64 (f64.const 2.220446049250313e-16)) - (global $~lib/builtins/f64.NaN f64 (f64.const nan:0x8000000000000)) (global $HEAP_BASE i32 (i32.const 48)) (export "memory" (memory $0)) (export "table" (table $0)) @@ -1925,683 +1923,6 @@ call $~lib/env/abort unreachable end - block $~lib/builtins/isNaN|inlined.4 (result i32) - get_global $~lib/builtins/f32.NaN - set_local $4 - get_local $4 - get_local $4 - f32.ne - end - i32.const 0 - i32.ne - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 317 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.0 (result i32) - get_global $~lib/builtins/f32.MIN_SAFE_INTEGER - f32.const 1 - f32.sub - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 318 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.1 (result i32) - get_global $~lib/builtins/f32.MIN_SAFE_INTEGER - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 319 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.2 (result i32) - f32.const 0 - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 320 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.3 (result i32) - f32.const -0 - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 321 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.4 (result i32) - f32.const nan:0x400000 - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 322 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.5 (result i32) - f32.const inf - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 323 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.6 (result i32) - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 324 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.7 (result i32) - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.const 1 - f32.add - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 325 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isSafeInteger|inlined.8 (result i32) - f32.const 0.5 - set_local $4 - get_local $4 - f32.abs - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - f32.le - tee_local $0 - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 326 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.0 (result i32) - f32.const 0 - set_local $4 - block $~lib/builtins/isFinite|inlined.8 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 327 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.1 (result i32) - f32.const -0 - set_local $4 - block $~lib/builtins/isFinite|inlined.9 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 328 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.2 (result i32) - f32.const nan:0x400000 - set_local $4 - block $~lib/builtins/isFinite|inlined.10 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 329 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.3 (result i32) - f32.const inf - set_local $4 - block $~lib/builtins/isFinite|inlined.11 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 330 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.4 (result i32) - get_global $~lib/builtins/f32.EPSILON - set_local $4 - block $~lib/builtins/isFinite|inlined.12 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 331 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.5 (result i32) - f32.const 1 - set_local $4 - block $~lib/builtins/isFinite|inlined.13 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 332 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.6 (result i32) - f32.const -1 - set_local $4 - block $~lib/builtins/isFinite|inlined.14 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 333 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.7 (result i32) - get_global $~lib/builtins/f32.MIN_SAFE_INTEGER - set_local $4 - block $~lib/builtins/isFinite|inlined.15 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 334 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.8 (result i32) - get_global $~lib/builtins/f32.MAX_SAFE_INTEGER - set_local $4 - block $~lib/builtins/isFinite|inlined.16 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 335 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.9 (result i32) - f32.const 0.5 - set_local $4 - block $~lib/builtins/isFinite|inlined.17 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 336 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f32.isInteger|inlined.10 (result i32) - f32.const -1.5 - set_local $4 - block $~lib/builtins/isFinite|inlined.18 (result i32) - get_local $4 - get_local $4 - f32.sub - f32.const 0 - f32.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $4 - f32.trunc - get_local $4 - f32.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 337 - i32.const 0 - call $~lib/env/abort - unreachable - end get_global $~lib/builtins/f64.MIN_NORMAL_VALUE f64.const 2.2250738585072014e-308 f64.eq @@ -2609,7 +1930,7 @@ if i32.const 0 i32.const 8 - i32.const 339 + i32.const 318 i32.const 0 call $~lib/env/abort unreachable @@ -2621,7 +1942,7 @@ if i32.const 0 i32.const 8 - i32.const 340 + i32.const 319 i32.const 0 call $~lib/env/abort unreachable @@ -2633,7 +1954,7 @@ if i32.const 0 i32.const 8 - i32.const 341 + i32.const 320 i32.const 0 call $~lib/env/abort unreachable @@ -2645,7 +1966,7 @@ if i32.const 0 i32.const 8 - i32.const 342 + i32.const 321 i32.const 0 call $~lib/env/abort unreachable @@ -2657,7 +1978,7 @@ if i32.const 0 i32.const 8 - i32.const 343 + i32.const 322 i32.const 0 call $~lib/env/abort unreachable @@ -2669,684 +1990,7 @@ if i32.const 0 i32.const 8 - i32.const 344 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/isNaN|inlined.4 (result i32) - get_global $~lib/builtins/f64.NaN - set_local $5 - get_local $5 - get_local $5 - f64.ne - end - i32.const 0 - i32.ne - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 345 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.0 (result i32) - get_global $~lib/builtins/f64.MIN_SAFE_INTEGER - f64.const 1 - f64.sub - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 346 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.1 (result i32) - get_global $~lib/builtins/f64.MIN_SAFE_INTEGER - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 347 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.2 (result i32) - f64.const 0 - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 348 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.3 (result i32) - f64.const -0 - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 349 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.4 (result i32) - f64.const nan:0x8000000000000 - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 350 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.5 (result i32) - f64.const inf - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 351 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.6 (result i32) - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 352 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.7 (result i32) - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.const 1 - f64.add - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 353 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isSafeInteger|inlined.8 (result i32) - f64.const 0.5 - set_local $5 - get_local $5 - f64.abs - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - f64.le - tee_local $0 - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 354 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.0 (result i32) - f64.const 0 - set_local $5 - block $~lib/builtins/isFinite|inlined.8 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 355 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.1 (result i32) - f64.const -0 - set_local $5 - block $~lib/builtins/isFinite|inlined.9 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 356 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.2 (result i32) - f64.const nan:0x8000000000000 - set_local $5 - block $~lib/builtins/isFinite|inlined.10 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 357 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.3 (result i32) - f64.const inf - set_local $5 - block $~lib/builtins/isFinite|inlined.11 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 358 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.4 (result i32) - get_global $~lib/builtins/f64.EPSILON - set_local $5 - block $~lib/builtins/isFinite|inlined.12 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 359 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.5 (result i32) - f64.const 1 - set_local $5 - block $~lib/builtins/isFinite|inlined.13 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 360 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.6 (result i32) - f64.const -1 - set_local $5 - block $~lib/builtins/isFinite|inlined.14 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 361 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.7 (result i32) - get_global $~lib/builtins/f64.MIN_SAFE_INTEGER - set_local $5 - block $~lib/builtins/isFinite|inlined.15 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 362 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.8 (result i32) - get_global $~lib/builtins/f64.MAX_SAFE_INTEGER - set_local $5 - block $~lib/builtins/isFinite|inlined.16 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 1 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 363 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.9 (result i32) - f64.const 0.5 - set_local $5 - block $~lib/builtins/isFinite|inlined.17 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 364 - i32.const 0 - call $~lib/env/abort - unreachable - end - block $~lib/builtins/f64.isInteger|inlined.10 (result i32) - f64.const -1.5 - set_local $5 - block $~lib/builtins/isFinite|inlined.18 (result i32) - get_local $5 - get_local $5 - f64.sub - f64.const 0 - f64.eq - end - tee_local $0 - i32.const 0 - i32.ne - if (result i32) - get_local $5 - f64.trunc - get_local $5 - f64.eq - else - get_local $0 - end - end - i32.const 0 - i32.ne - i32.const 0 - i32.eq - i32.eqz - if - i32.const 0 - i32.const 8 - i32.const 365 + i32.const 323 i32.const 0 call $~lib/env/abort unreachable @@ -3526,7 +2170,7 @@ f64.const 1 f64.trunc drop - block $~lib/builtins/isNaN|inlined.5 (result i32) + block $~lib/builtins/isNaN|inlined.4 (result i32) f64.const 1 set_local $5 get_local $5 diff --git a/tests/compiler/number.optimized.wat b/tests/compiler/number.optimized.wat new file mode 100644 index 00000000..e33548e8 --- /dev/null +++ b/tests/compiler/number.optimized.wat @@ -0,0 +1,2839 @@ +(module + (type $ii (func (param i32) (result i32))) + (type $iiiiv (func (param i32 i32 i32 i32))) + (type $iiiv (func (param i32 i32 i32))) + (type $iii (func (param i32 i32) (result i32))) + (type $Fi (func (param f64) (result i32))) + (type $iFi (func (param i32 f64) (result i32))) + (type $iIiIiIii (func (param i32 i64 i32 i64 i32 i64 i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) + (type $v (func)) + (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32))) + (memory $0 1) + (data (i32.const 8) "\01\00\00\000") + (data (i32.const 16) "\17\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00s\00t\00r\00i\00n\00g\00.\00t\00s") + (data (i32.const 72) "\90\01\00\00\00\00\00\000\000\000\001\000\002\000\003\000\004\000\005\000\006\000\007\000\008\000\009\001\000\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\008\001\009\002\000\002\001\002\002\002\003\002\004\002\005\002\006\002\007\002\008\002\009\003\000\003\001\003\002\003\003\003\004\003\005\003\006\003\007\003\008\003\009\004\000\004\001\004\002\004\003\004\004\004\005\004\006\004\007\004\008\004\009\005\000\005\001\005\002\005\003\005\004\005\005\005\006\005\007\005\008\005\009\006\000\006\001\006\002\006\003\006\004\006\005\006\006\006\007\006\008\006\009\007\000\007\001\007\002\007\003\007\004\007\005\007\006\007\007\007\008\007\009\008\000\008\001\008\002\008\003\008\004\008\005\008\006\008\007\008\008\008\009\009\000\009\001\009\002\009\003\009\004\009\005\009\006\009\007\009\008\009\009") + (data (i32.const 584) "H\00\00\00d") + (data (i32.const 592) "\01\00\00\001") + (data (i32.const 600) "\t\00\00\00n\00u\00m\00b\00e\00r\00.\00t\00s") + (data (i32.const 624) "\03\00\00\000\00.\000") + (data (i32.const 640) "\03\00\00\00N\00a\00N") + (data (i32.const 656) "\t\00\00\00-\00I\00n\00f\00i\00n\00i\00t\00y") + (data (i32.const 680) "\08\00\00\00I\00n\00f\00i\00n\00i\00t\00y") + (data (i32.const 704) "\b8\02\00\00\00\00\00\00\88\02\1c\08\a0\d5\8f\fav\bf>\a2\7f\e1\ae\bav\acU0 \fb\16\8b\ea5\ce]J\89B\cf-;eU\aa\b0k\9a\dfE\1a=\03\cf\1a\e6\ca\c6\9a\c7\17\fep\abO\dc\bc\be\fc\b1w\ff\0c\d6kA\ef\91V\be<\fc\7f\90\ad\1f\d0\8d\83\9aU1(\\Q\d3\b5\c9\a6\ad\8f\acq\9d\cb\8b\ee#w\"\9c\eamSx@\91I\cc\aeW\ce\b6]y\12<\827V\fbM6\94\10\c2O\98H8o\ea\96\90\c7:\82%\cb\85t\d7\f4\97\bf\97\cd\cf\86\a0\e5\ac*\17\98\n4\ef\8e\b25*\fbg8\b2;?\c6\d2\df\d4\c8\84\ba\cd\d3\1a\'D\dd\c5\96\c9%\bb\ce\9fk\93\84\a5b}$l\ac\db\f6\da_\0dXf\ab\a3&\f1\c3\de\93\f8\e2\f3\b8\80\ff\aa\a8\ad\b5\b5\8bJ|l\05_b\87S0\c14`\ff\bc\c9U&\ba\91\8c\85N\96\bd~)p$w\f9\df\8f\b8\e5\b8\9f\bd\df\a6\94}t\88\cf_\a9\f8\cf\9b\a8\8f\93pD\b9k\15\0f\bf\f8\f0\08\8a\b611eU%\b0\cd\ac\7f{\d0\c6\e2?\99\06;+*\c4\10\\\e4\d3\92si\99$$\aa\0e\ca\00\83\f2\b5\87\fd\eb\1a\11\92d\08\e5\bc\cc\88Po\t\cc\bc\8c,e\19\e2X\17\b7\d1\00\00\00\00\00\00@\9c\00\00\00\00\10\a5\d4\e8\00\00b\ac\c5\ebx\ad\84\t\94\f8x9?\81\b3\15\07\c9{\ce\97\c0p\\\ea{\ce2~\8fh\80\e9\ab\a48\d2\d5E\"\9a\17&\'O\9f\'\fb\c4\d41\a2c\ed\a8\ad\c8\8c8e\de\b0\dbe\ab\1a\8e\08\c7\83\9a\1dqB\f9\1d]\c4X\e7\1b\a6,iM\92\ea\8dp\1ad\ee\01\daJw\ef\9a\99\a3m\a2\85k}\b4{x\t\f2w\18\ddy\a1\e4T\b4\c2\c5\9b[\92\86[\86=]\96\c8\c5S5\c8\b3\a0\97\fa\\\b4*\95\e3_\a0\99\bd\9fF\de%\8c9\db4\c2\9b\a5\\\9f\98\a3r\9a\c6\f6\ce\be\e9TS\bf\dc\b7\e2A\"\f2\17\f3\fc\88\a5x\\\d3\9b\ce \cc\dfS!{\f3Z\16\98:0\1f\97\dc\b5\a0\e2\96\b3\e3\\S\d1\d9\a8(F32.NaN)); + +assert(F32.isSafeInteger(f32.MIN_SAFE_INTEGER - 1) == false); +assert(F32.isSafeInteger(f32.MIN_SAFE_INTEGER) == true); +assert(F32.isSafeInteger(+0.0) == true); +assert(F32.isSafeInteger(-0.0) == true); +assert(F32.isSafeInteger(NaN) == false); +assert(F32.isSafeInteger(Infinity) == false); +assert(F32.isSafeInteger(f32.MAX_SAFE_INTEGER) == true); +assert(F32.isSafeInteger(f32.MAX_SAFE_INTEGER + 1) == false); +assert(F32.isSafeInteger(0.5) == false); +assert(F32.isInteger(+0.0) == true); +assert(F32.isInteger(-0.0) == true); +assert(F32.isInteger(NaN) == false); +assert(F32.isInteger(Infinity) == false); +assert(F32.isInteger(f32.EPSILON) == false); +assert(F32.isInteger(+1.0) == true); +assert(F32.isInteger(-1.0) == true); +assert(F32.isInteger(f32.MIN_SAFE_INTEGER) == true); +assert(F32.isInteger(f32.MAX_SAFE_INTEGER) == true); +assert(F32.isInteger(+0.5) == false); +assert(F32.isInteger(-1.5) == false); + +assert(isNaN(F64.NaN)); + +assert(F64.isSafeInteger(f64.MIN_SAFE_INTEGER - 1) == false); +assert(F64.isSafeInteger(f64.MIN_SAFE_INTEGER) == true); +assert(F64.isSafeInteger(+0.0) == true); +assert(F64.isSafeInteger(-0.0) == true); +assert(F64.isSafeInteger(NaN) == false); +assert(F64.isSafeInteger(Infinity) == false); +assert(F64.isSafeInteger(f64.MAX_SAFE_INTEGER) == true); +assert(F64.isSafeInteger(f64.MAX_SAFE_INTEGER + 1) == false); +assert(F64.isSafeInteger(0.5) == false); +assert(F64.isInteger(+0.0) == true); +assert(F64.isInteger(-0.0) == true); +assert(F64.isInteger(NaN) == false); +assert(F64.isInteger(Infinity) == false); +assert(F64.isInteger(f64.EPSILON) == false); +assert(F64.isInteger(+1.0) == true); +assert(F64.isInteger(-1.0) == true); +assert(F64.isInteger(f64.MIN_SAFE_INTEGER) == true); +assert(F64.isInteger(f64.MAX_SAFE_INTEGER) == true); +assert(F64.isInteger(+0.5) == false); +assert(F64.isInteger(-1.5) == false); diff --git a/tests/compiler/number.untouched.wat b/tests/compiler/number.untouched.wat new file mode 100644 index 00000000..15718bef --- /dev/null +++ b/tests/compiler/number.untouched.wat @@ -0,0 +1,4475 @@ +(module + (type $ii (func (param i32) (result i32))) + (type $iiiiv (func (param i32 i32 i32 i32))) + (type $iiiv (func (param i32 i32 i32))) + (type $iii (func (param i32 i32) (result i32))) + (type $iiiiii (func (param i32 i32 i32 i32 i32) (result i32))) + (type $Fi (func (param f64) (result i32))) + (type $iFi (func (param i32 f64) (result i32))) + (type $iIiIiIii (func (param i32 i64 i32 i64 i32 i64 i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) + (type $iiiiiv (func (param i32 i32 i32 i32 i32))) + (type $iv (func (param i32))) + (type $fi (func (param f32) (result i32))) + (type $v (func)) + (import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32))) + (memory $0 1) + (data (i32.const 8) "\01\00\00\000\00") + (data (i32.const 16) "\17\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00s\00t\00r\00i\00n\00g\00.\00t\00s\00") + (data (i32.const 72) "\90\01\00\00\00\00\00\000\000\000\001\000\002\000\003\000\004\000\005\000\006\000\007\000\008\000\009\001\000\001\001\001\002\001\003\001\004\001\005\001\006\001\007\001\008\001\009\002\000\002\001\002\002\002\003\002\004\002\005\002\006\002\007\002\008\002\009\003\000\003\001\003\002\003\003\003\004\003\005\003\006\003\007\003\008\003\009\004\000\004\001\004\002\004\003\004\004\004\005\004\006\004\007\004\008\004\009\005\000\005\001\005\002\005\003\005\004\005\005\005\006\005\007\005\008\005\009\006\000\006\001\006\002\006\003\006\004\006\005\006\006\006\007\006\008\006\009\007\000\007\001\007\002\007\003\007\004\007\005\007\006\007\007\007\008\007\009\008\000\008\001\008\002\008\003\008\004\008\005\008\006\008\007\008\008\008\009\009\000\009\001\009\002\009\003\009\004\009\005\009\006\009\007\009\008\009\009\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data (i32.const 584) "H\00\00\00d\00\00\00") + (data (i32.const 592) "\01\00\00\001\00") + (data (i32.const 600) "\t\00\00\00n\00u\00m\00b\00e\00r\00.\00t\00s\00") + (data (i32.const 624) "\03\00\00\000\00.\000\00") + (data (i32.const 640) "\03\00\00\00N\00a\00N\00") + (data (i32.const 656) "\t\00\00\00-\00I\00n\00f\00i\00n\00i\00t\00y\00") + (data (i32.const 680) "\08\00\00\00I\00n\00f\00i\00n\00i\00t\00y\00") + (data (i32.const 704) "\b8\02\00\00\00\00\00\00\88\02\1c\08\a0\d5\8f\fav\bf>\a2\7f\e1\ae\bav\acU0 \fb\16\8b\ea5\ce]J\89B\cf-;eU\aa\b0k\9a\dfE\1a=\03\cf\1a\e6\ca\c6\9a\c7\17\fep\abO\dc\bc\be\fc\b1w\ff\0c\d6kA\ef\91V\be<\fc\7f\90\ad\1f\d0\8d\83\9aU1(\\Q\d3\b5\c9\a6\ad\8f\acq\9d\cb\8b\ee#w\"\9c\eamSx@\91I\cc\aeW\ce\b6]y\12<\827V\fbM6\94\10\c2O\98H8o\ea\96\90\c7:\82%\cb\85t\d7\f4\97\bf\97\cd\cf\86\a0\e5\ac*\17\98\n4\ef\8e\b25*\fbg8\b2;?\c6\d2\df\d4\c8\84\ba\cd\d3\1a\'D\dd\c5\96\c9%\bb\ce\9fk\93\84\a5b}$l\ac\db\f6\da_\0dXf\ab\a3&\f1\c3\de\93\f8\e2\f3\b8\80\ff\aa\a8\ad\b5\b5\8bJ|l\05_b\87S0\c14`\ff\bc\c9U&\ba\91\8c\85N\96\bd~)p$w\f9\df\8f\b8\e5\b8\9f\bd\df\a6\94}t\88\cf_\a9\f8\cf\9b\a8\8f\93pD\b9k\15\0f\bf\f8\f0\08\8a\b611eU%\b0\cd\ac\7f{\d0\c6\e2?\99\06;+*\c4\10\\\e4\d3\92si\99$$\aa\0e\ca\00\83\f2\b5\87\fd\eb\1a\11\92d\08\e5\bc\cc\88Po\t\cc\bc\8c,e\19\e2X\17\b7\d1\00\00\00\00\00\00@\9c\00\00\00\00\10\a5\d4\e8\00\00b\ac\c5\ebx\ad\84\t\94\f8x9?\81\b3\15\07\c9{\ce\97\c0p\\\ea{\ce2~\8fh\80\e9\ab\a48\d2\d5E\"\9a\17&\'O\9f\'\fb\c4\d41\a2c\ed\a8\ad\c8\8c8e\de\b0\dbe\ab\1a\8e\08\c7\83\9a\1dqB\f9\1d]\c4X\e7\1b\a6,iM\92\ea\8dp\1ad\ee\01\daJw\ef\9a\99\a3m\a2\85k}\b4{x\t\f2w\18\ddy\a1\e4T\b4\c2\c5\9b[\92\86[\86=]\96\c8\c5S5\c8\b3\a0\97\fa\\\b4*\95\e3_\a0\99\bd\9fF\de%\8c9\db4\c2\9b\a5\\\9f\98\a3r\9a\c6\f6\ce\be\e9TS\bf\dc\b7\e2A\"\f2\17\f3\fc\88\a5x\\\d3\9b\ce \cc\dfS!{\f3Z\16\98:0\1f\97\dc\b5\a0\e2\96\b3\e3\\S\d1\d9\a8|inlined.0 (result i64) + i32.const 0 + set_local $8 + get_local $3 + get_local $6 + i32.const 2 + i32.shl + i32.add + get_local $8 + i32.add + i64.load32_u offset=8 + end + set_local $9 + block $~lib/internal/arraybuffer/LOAD|inlined.1 (result i64) + i32.const 0 + set_local $8 + get_local $3 + get_local $7 + i32.const 2 + i32.shl + i32.add + get_local $8 + i32.add + i64.load32_u offset=8 + end + set_local $10 + get_local $2 + i32.const 4 + i32.sub + set_local $2 + get_local $0 + get_local $2 + i32.const 1 + i32.shl + i32.add + get_local $9 + get_local $10 + i64.const 32 + i64.shl + i64.or + i64.store offset=4 + end + br $continue|0 + end + end + end + get_local $1 + i32.const 100 + i32.ge_u + if + get_local $1 + i32.const 100 + i32.div_u + set_local $7 + get_local $1 + i32.const 100 + i32.rem_u + set_local $6 + get_local $7 + set_local $1 + get_local $2 + i32.const 2 + i32.sub + set_local $2 + block $~lib/internal/arraybuffer/LOAD|inlined.0 (result i32) + i32.const 0 + set_local $5 + get_local $3 + get_local $6 + i32.const 2 + i32.shl + i32.add + get_local $5 + i32.add + i32.load offset=8 + end + set_local $5 + get_local $0 + get_local $2 + i32.const 1 + i32.shl + i32.add + get_local $5 + i32.store offset=4 + end + get_local $1 + i32.const 10 + i32.ge_u + if + get_local $2 + i32.const 2 + i32.sub + set_local $2 + block $~lib/internal/arraybuffer/LOAD|inlined.1 (result i32) + i32.const 0 + set_local $5 + get_local $3 + get_local $1 + i32.const 2 + i32.shl + i32.add + get_local $5 + i32.add + i32.load offset=8 + end + set_local $5 + get_local $0 + get_local $2 + i32.const 1 + i32.shl + i32.add + get_local $5 + i32.store offset=4 + else + get_local $2 + i32.const 1 + i32.sub + set_local $2 + get_global $~lib/internal/string/CharCode._0 + get_local $1 + i32.add + set_local $5 + get_local $0 + get_local $2 + i32.const 1 + i32.shl + i32.add + get_local $5 + i32.store16 offset=4 + end + ) + (func $~lib/internal/number/itoa32 (; 5 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + get_local $0 + i32.eqz + if + i32.const 8 + return + end + get_local $0 + i32.const 0 + i32.lt_s + set_local $1 + get_local $1 + if + i32.const 0 + get_local $0 + i32.sub + set_local $0 + end + get_local $0 + call $~lib/internal/number/decimalCount32 + get_local $1 + i32.add + set_local $2 + get_local $2 + call $~lib/internal/string/allocateUnsafe + set_local $3 + get_local $3 + get_local $0 + get_local $2 + call $~lib/internal/number/utoa32_lut + get_local $1 + if + get_local $3 + get_global $~lib/internal/string/CharCode.MINUS + i32.store16 offset=4 + end + get_local $3 + ) + (func $~lib/internal/number/itoa (; 6 ;) (type $ii) (param $0 i32) (result i32) + get_local $0 + call $~lib/internal/number/itoa32 + return + ) + (func $~lib/number/I32#toString (; 7 ;) (type $ii) (param $0 i32) (result i32) + get_local $0 + call $~lib/internal/number/itoa + ) + (func $~lib/internal/string/compareUnsafe (; 8 ;) (type $iiiiii) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + i32.const 0 + set_local $5 + get_local $0 + get_local $1 + i32.const 1 + i32.shl + i32.add + set_local $6 + get_local $2 + get_local $3 + i32.const 1 + i32.shl + i32.add + set_local $7 + block $break|0 + loop $continue|0 + get_local $4 + if (result i32) + get_local $6 + i32.load16_u offset=4 + get_local $7 + i32.load16_u offset=4 + i32.sub + tee_local $5 + i32.eqz + else + get_local $4 + end + if + block + get_local $4 + i32.const 1 + i32.sub + set_local $4 + get_local $6 + i32.const 2 + i32.add + set_local $6 + get_local $7 + i32.const 2 + i32.add + set_local $7 + end + br $continue|0 + end + end + end + get_local $5 + ) + (func $~lib/string/String.__eq (; 9 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + get_local $0 + get_local $1 + i32.eq + if + i32.const 1 + return + end + get_local $0 + i32.const 0 + i32.eq + tee_local $2 + if (result i32) + get_local $2 + else + get_local $1 + i32.const 0 + i32.eq + end + if + i32.const 0 + return + end + get_local $0 + i32.load + set_local $3 + get_local $3 + get_local $1 + i32.load + i32.ne + if + i32.const 0 + return + end + get_local $0 + i32.const 0 + get_local $1 + i32.const 0 + get_local $3 + call $~lib/internal/string/compareUnsafe + i32.eqz + ) + (func $~lib/builtins/isFinite (; 10 ;) (type $Fi) (param $0 f64) (result i32) + get_local $0 + get_local $0 + f64.sub + f64.const 0 + f64.eq + ) + (func $~lib/builtins/isNaN (; 11 ;) (type $Fi) (param $0 f64) (result i32) + get_local $0 + get_local $0 + f64.ne + ) + (func $~lib/internal/number/genDigits (; 12 ;) (type $iIiIiIii) (param $0 i32) (param $1 i64) (param $2 i32) (param $3 i64) (param $4 i32) (param $5 i64) (param $6 i32) (result i32) + (local $7 i32) + (local $8 i64) + (local $9 i64) + (local $10 i64) + (local $11 i32) + (local $12 i32) + (local $13 i64) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i64) + (local $20 i64) + (local $21 i32) + (local $22 i32) + i32.const 0 + get_local $4 + i32.sub + set_local $7 + i64.const 1 + get_local $7 + i64.extend_s/i32 + i64.shl + set_local $8 + get_local $8 + i64.const 1 + i64.sub + set_local $9 + get_local $3 + get_local $1 + i64.sub + set_local $10 + get_local $4 + set_local $11 + get_local $3 + get_local $7 + i64.extend_s/i32 + i64.shr_u + i32.wrap/i64 + set_local $12 + get_local $3 + get_local $9 + i64.and + set_local $13 + get_local $12 + call $~lib/internal/number/decimalCount32 + set_local $14 + get_local $6 + set_local $15 + block $~lib/internal/number/POWERS10|inlined.0 (result i32) + i32.const 2064 + end + i32.load + set_local $16 + block $break|0 + loop $continue|0 + get_local $14 + i32.const 0 + i32.gt_s + if + block + block $break|1 + block $case10|1 + block $case9|1 + block $case8|1 + block $case7|1 + block $case6|1 + block $case5|1 + block $case4|1 + block $case3|1 + block $case2|1 + block $case1|1 + block $case0|1 + get_local $14 + set_local $18 + get_local $18 + i32.const 10 + i32.eq + br_if $case0|1 + get_local $18 + i32.const 9 + i32.eq + br_if $case1|1 + get_local $18 + i32.const 8 + i32.eq + br_if $case2|1 + get_local $18 + i32.const 7 + i32.eq + br_if $case3|1 + get_local $18 + i32.const 6 + i32.eq + br_if $case4|1 + get_local $18 + i32.const 5 + i32.eq + br_if $case5|1 + get_local $18 + i32.const 4 + i32.eq + br_if $case6|1 + get_local $18 + i32.const 3 + i32.eq + br_if $case7|1 + get_local $18 + i32.const 2 + i32.eq + br_if $case8|1 + get_local $18 + i32.const 1 + i32.eq + br_if $case9|1 + br $case10|1 + end + block + get_local $12 + i32.const 1000000000 + i32.div_u + set_local $17 + get_local $12 + i32.const 1000000000 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + i32.const 100000000 + i32.div_u + set_local $17 + get_local $12 + i32.const 100000000 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + i32.const 10000000 + i32.div_u + set_local $17 + get_local $12 + i32.const 10000000 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + i32.const 1000000 + i32.div_u + set_local $17 + get_local $12 + i32.const 1000000 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + i32.const 100000 + i32.div_u + set_local $17 + get_local $12 + i32.const 100000 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + i32.const 10000 + i32.div_u + set_local $17 + get_local $12 + i32.const 10000 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + i32.const 1000 + i32.div_u + set_local $17 + get_local $12 + i32.const 1000 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + i32.const 100 + i32.div_u + set_local $17 + get_local $12 + i32.const 100 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + i32.const 10 + i32.div_u + set_local $17 + get_local $12 + i32.const 10 + i32.rem_u + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + get_local $12 + set_local $17 + i32.const 0 + set_local $12 + br $break|1 + unreachable + end + unreachable + end + block + i32.const 0 + set_local $17 + br $break|1 + unreachable + end + unreachable + end + get_local $17 + get_local $15 + i32.or + if + get_local $0 + block (result i32) + get_local $15 + tee_local $18 + i32.const 1 + i32.add + set_local $15 + get_local $18 + end + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/CharCode._0 + get_local $17 + i32.const 65535 + i32.and + i32.add + i32.store16 offset=4 + end + get_local $14 + i32.const 1 + i32.sub + set_local $14 + get_local $12 + i64.extend_u/i32 + get_local $7 + i64.extend_s/i32 + i64.shl + get_local $13 + i64.add + set_local $19 + get_local $19 + get_local $5 + i64.le_u + if + get_global $~lib/internal/number/_K + get_local $14 + i32.add + set_global $~lib/internal/number/_K + block $~lib/internal/arraybuffer/LOAD|inlined.2 (result i64) + i32.const 0 + set_local $18 + get_local $16 + get_local $14 + i32.const 2 + i32.shl + i32.add + get_local $18 + i32.add + i64.load32_u offset=8 + end + get_local $7 + i64.extend_s/i32 + i64.shl + set_local $20 + get_local $0 + get_local $15 + i32.const 1 + i32.sub + i32.const 1 + i32.shl + i32.add + set_local $18 + get_local $18 + i32.load16_u offset=4 + set_local $21 + block $break|2 + loop $continue|2 + get_local $19 + get_local $10 + i64.lt_u + tee_local $22 + if (result i32) + get_local $5 + get_local $19 + i64.sub + get_local $20 + i64.ge_u + else + get_local $22 + end + tee_local $22 + if (result i32) + get_local $19 + get_local $20 + i64.add + get_local $10 + i64.lt_u + tee_local $22 + if (result i32) + get_local $22 + else + get_local $10 + get_local $19 + i64.sub + get_local $19 + get_local $20 + i64.add + get_local $10 + i64.sub + i64.gt_u + end + else + get_local $22 + end + if + block + get_local $21 + i32.const 1 + i32.sub + set_local $21 + get_local $19 + get_local $20 + i64.add + set_local $19 + end + br $continue|2 + end + end + end + get_local $18 + get_local $21 + i32.store16 offset=4 + get_local $15 + return + end + end + br $continue|0 + end + end + end + block $break|3 + loop $continue|3 + i32.const 1 + if + block + get_local $13 + i64.const 10 + i64.mul + set_local $13 + get_local $5 + i64.const 10 + i64.mul + set_local $5 + get_local $13 + get_local $7 + i64.extend_s/i32 + i64.shr_u + set_local $19 + get_local $19 + get_local $15 + i64.extend_s/i32 + i64.or + i64.const 0 + i64.ne + if + get_local $0 + block (result i32) + get_local $15 + tee_local $17 + i32.const 1 + i32.add + set_local $15 + get_local $17 + end + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/CharCode._0 + get_local $19 + i32.wrap/i64 + i32.const 65535 + i32.and + i32.add + i32.store16 offset=4 + end + get_local $13 + get_local $9 + i64.and + set_local $13 + get_local $14 + i32.const 1 + i32.sub + set_local $14 + get_local $13 + get_local $5 + i64.lt_u + if + get_global $~lib/internal/number/_K + get_local $14 + i32.add + set_global $~lib/internal/number/_K + get_local $10 + block $~lib/internal/arraybuffer/LOAD|inlined.3 (result i64) + i32.const 0 + get_local $14 + i32.sub + set_local $17 + i32.const 0 + set_local $21 + get_local $16 + get_local $17 + i32.const 2 + i32.shl + i32.add + get_local $21 + i32.add + i64.load32_u offset=8 + end + i64.mul + set_local $10 + get_local $0 + get_local $15 + i32.const 1 + i32.sub + i32.const 1 + i32.shl + i32.add + set_local $21 + get_local $21 + i32.load16_u offset=4 + set_local $17 + block $break|4 + loop $continue|4 + get_local $13 + get_local $10 + i64.lt_u + tee_local $18 + if (result i32) + get_local $5 + get_local $13 + i64.sub + get_local $8 + i64.ge_u + else + get_local $18 + end + tee_local $18 + if (result i32) + get_local $13 + get_local $8 + i64.add + get_local $10 + i64.lt_u + tee_local $18 + if (result i32) + get_local $18 + else + get_local $10 + get_local $13 + i64.sub + get_local $13 + get_local $8 + i64.add + get_local $10 + i64.sub + i64.gt_u + end + else + get_local $18 + end + if + block + get_local $17 + i32.const 1 + i32.sub + set_local $17 + get_local $13 + get_local $8 + i64.add + set_local $13 + end + br $continue|4 + end + end + end + get_local $21 + get_local $17 + i32.store16 offset=4 + get_local $15 + return + end + end + br $continue|3 + end + end + end + get_local $15 + ) + (func $~lib/internal/memory/memcpy (; 13 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + block $break|0 + loop $continue|0 + get_local $2 + if (result i32) + get_local $1 + i32.const 3 + i32.and + else + get_local $2 + end + if + block + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + get_local $2 + i32.const 1 + i32.sub + set_local $2 + end + br $continue|0 + end + end + end + get_local $0 + i32.const 3 + i32.and + i32.const 0 + i32.eq + if + block $break|1 + loop $continue|1 + get_local $2 + i32.const 16 + i32.ge_u + if + block + get_local $0 + get_local $1 + i32.load + i32.store + get_local $0 + i32.const 4 + i32.add + get_local $1 + i32.const 4 + i32.add + i32.load + i32.store + get_local $0 + i32.const 8 + i32.add + get_local $1 + i32.const 8 + i32.add + i32.load + i32.store + get_local $0 + i32.const 12 + i32.add + get_local $1 + i32.const 12 + i32.add + i32.load + i32.store + get_local $1 + i32.const 16 + i32.add + set_local $1 + get_local $0 + i32.const 16 + i32.add + set_local $0 + get_local $2 + i32.const 16 + i32.sub + set_local $2 + end + br $continue|1 + end + end + end + get_local $2 + i32.const 8 + i32.and + if + get_local $0 + get_local $1 + i32.load + i32.store + get_local $0 + i32.const 4 + i32.add + get_local $1 + i32.const 4 + i32.add + i32.load + i32.store + get_local $0 + i32.const 8 + i32.add + set_local $0 + get_local $1 + i32.const 8 + i32.add + set_local $1 + end + get_local $2 + i32.const 4 + i32.and + if + get_local $0 + get_local $1 + i32.load + i32.store + get_local $0 + i32.const 4 + i32.add + set_local $0 + get_local $1 + i32.const 4 + i32.add + set_local $1 + end + get_local $2 + i32.const 2 + i32.and + if + get_local $0 + get_local $1 + i32.load16_u + i32.store16 + get_local $0 + i32.const 2 + i32.add + set_local $0 + get_local $1 + i32.const 2 + i32.add + set_local $1 + end + get_local $2 + i32.const 1 + i32.and + if + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + end + return + end + get_local $2 + i32.const 32 + i32.ge_u + if + block $break|2 + block $case2|2 + block $case1|2 + block $case0|2 + get_local $0 + i32.const 3 + i32.and + set_local $5 + get_local $5 + i32.const 1 + i32.eq + br_if $case0|2 + get_local $5 + i32.const 2 + i32.eq + br_if $case1|2 + get_local $5 + i32.const 3 + i32.eq + br_if $case2|2 + br $break|2 + end + block + get_local $1 + i32.load + set_local $3 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + get_local $2 + i32.const 3 + i32.sub + set_local $2 + block $break|3 + loop $continue|3 + get_local $2 + i32.const 17 + i32.ge_u + if + block + get_local $1 + i32.const 1 + i32.add + i32.load + set_local $4 + get_local $0 + get_local $3 + i32.const 24 + i32.shr_u + get_local $4 + i32.const 8 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 5 + i32.add + i32.load + set_local $3 + get_local $0 + i32.const 4 + i32.add + get_local $4 + i32.const 24 + i32.shr_u + get_local $3 + i32.const 8 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 9 + i32.add + i32.load + set_local $4 + get_local $0 + i32.const 8 + i32.add + get_local $3 + i32.const 24 + i32.shr_u + get_local $4 + i32.const 8 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 13 + i32.add + i32.load + set_local $3 + get_local $0 + i32.const 12 + i32.add + get_local $4 + i32.const 24 + i32.shr_u + get_local $3 + i32.const 8 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 16 + i32.add + set_local $1 + get_local $0 + i32.const 16 + i32.add + set_local $0 + get_local $2 + i32.const 16 + i32.sub + set_local $2 + end + br $continue|3 + end + end + end + br $break|2 + unreachable + end + unreachable + end + block + get_local $1 + i32.load + set_local $3 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + get_local $2 + i32.const 2 + i32.sub + set_local $2 + block $break|4 + loop $continue|4 + get_local $2 + i32.const 18 + i32.ge_u + if + block + get_local $1 + i32.const 2 + i32.add + i32.load + set_local $4 + get_local $0 + get_local $3 + i32.const 16 + i32.shr_u + get_local $4 + i32.const 16 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 6 + i32.add + i32.load + set_local $3 + get_local $0 + i32.const 4 + i32.add + get_local $4 + i32.const 16 + i32.shr_u + get_local $3 + i32.const 16 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 10 + i32.add + i32.load + set_local $4 + get_local $0 + i32.const 8 + i32.add + get_local $3 + i32.const 16 + i32.shr_u + get_local $4 + i32.const 16 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 14 + i32.add + i32.load + set_local $3 + get_local $0 + i32.const 12 + i32.add + get_local $4 + i32.const 16 + i32.shr_u + get_local $3 + i32.const 16 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 16 + i32.add + set_local $1 + get_local $0 + i32.const 16 + i32.add + set_local $0 + get_local $2 + i32.const 16 + i32.sub + set_local $2 + end + br $continue|4 + end + end + end + br $break|2 + unreachable + end + unreachable + end + block + get_local $1 + i32.load + set_local $3 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + get_local $2 + i32.const 1 + i32.sub + set_local $2 + block $break|5 + loop $continue|5 + get_local $2 + i32.const 19 + i32.ge_u + if + block + get_local $1 + i32.const 3 + i32.add + i32.load + set_local $4 + get_local $0 + get_local $3 + i32.const 8 + i32.shr_u + get_local $4 + i32.const 24 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 7 + i32.add + i32.load + set_local $3 + get_local $0 + i32.const 4 + i32.add + get_local $4 + i32.const 8 + i32.shr_u + get_local $3 + i32.const 24 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 11 + i32.add + i32.load + set_local $4 + get_local $0 + i32.const 8 + i32.add + get_local $3 + i32.const 8 + i32.shr_u + get_local $4 + i32.const 24 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 15 + i32.add + i32.load + set_local $3 + get_local $0 + i32.const 12 + i32.add + get_local $4 + i32.const 8 + i32.shr_u + get_local $3 + i32.const 24 + i32.shl + i32.or + i32.store + get_local $1 + i32.const 16 + i32.add + set_local $1 + get_local $0 + i32.const 16 + i32.add + set_local $0 + get_local $2 + i32.const 16 + i32.sub + set_local $2 + end + br $continue|5 + end + end + end + br $break|2 + unreachable + end + unreachable + end + end + get_local $2 + i32.const 16 + i32.and + if + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + end + get_local $2 + i32.const 8 + i32.and + if + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + end + get_local $2 + i32.const 4 + i32.and + if + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + end + get_local $2 + i32.const 2 + i32.and + if + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + end + get_local $2 + i32.const 1 + i32.and + if + block (result i32) + get_local $0 + tee_local $5 + i32.const 1 + i32.add + set_local $0 + get_local $5 + end + block (result i32) + get_local $1 + tee_local $5 + i32.const 1 + i32.add + set_local $1 + get_local $5 + end + i32.load8_u + i32.store8 + end + ) + (func $~lib/internal/memory/memmove (; 14 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + get_local $0 + get_local $1 + i32.eq + if + return + end + get_local $1 + get_local $2 + i32.add + get_local $0 + i32.le_u + tee_local $3 + if (result i32) + get_local $3 + else + get_local $0 + get_local $2 + i32.add + get_local $1 + i32.le_u + end + if + get_local $0 + get_local $1 + get_local $2 + call $~lib/internal/memory/memcpy + return + end + get_local $0 + get_local $1 + i32.lt_u + if + get_local $1 + i32.const 7 + i32.and + get_local $0 + i32.const 7 + i32.and + i32.eq + if + block $break|0 + loop $continue|0 + get_local $0 + i32.const 7 + i32.and + if + block + get_local $2 + i32.eqz + if + return + end + get_local $2 + i32.const 1 + i32.sub + set_local $2 + block (result i32) + get_local $0 + tee_local $3 + i32.const 1 + i32.add + set_local $0 + get_local $3 + end + block (result i32) + get_local $1 + tee_local $3 + i32.const 1 + i32.add + set_local $1 + get_local $3 + end + i32.load8_u + i32.store8 + end + br $continue|0 + end + end + end + block $break|1 + loop $continue|1 + get_local $2 + i32.const 8 + i32.ge_u + if + block + get_local $0 + get_local $1 + i64.load + i64.store + get_local $2 + i32.const 8 + i32.sub + set_local $2 + get_local $0 + i32.const 8 + i32.add + set_local $0 + get_local $1 + i32.const 8 + i32.add + set_local $1 + end + br $continue|1 + end + end + end + end + block $break|2 + loop $continue|2 + get_local $2 + if + block + block (result i32) + get_local $0 + tee_local $3 + i32.const 1 + i32.add + set_local $0 + get_local $3 + end + block (result i32) + get_local $1 + tee_local $3 + i32.const 1 + i32.add + set_local $1 + get_local $3 + end + i32.load8_u + i32.store8 + get_local $2 + i32.const 1 + i32.sub + set_local $2 + end + br $continue|2 + end + end + end + else + get_local $1 + i32.const 7 + i32.and + get_local $0 + i32.const 7 + i32.and + i32.eq + if + block $break|3 + loop $continue|3 + get_local $0 + get_local $2 + i32.add + i32.const 7 + i32.and + if + block + get_local $2 + i32.eqz + if + return + end + get_local $0 + get_local $2 + i32.const 1 + i32.sub + tee_local $2 + i32.add + get_local $1 + get_local $2 + i32.add + i32.load8_u + i32.store8 + end + br $continue|3 + end + end + end + block $break|4 + loop $continue|4 + get_local $2 + i32.const 8 + i32.ge_u + if + block + get_local $2 + i32.const 8 + i32.sub + set_local $2 + get_local $0 + get_local $2 + i32.add + get_local $1 + get_local $2 + i32.add + i64.load + i64.store + end + br $continue|4 + end + end + end + end + block $break|5 + loop $continue|5 + get_local $2 + if + get_local $0 + get_local $2 + i32.const 1 + i32.sub + tee_local $2 + i32.add + get_local $1 + get_local $2 + i32.add + i32.load8_u + i32.store8 + br $continue|5 + end + end + end + end + ) + (func $~lib/internal/number/prettify (; 15 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + get_local $2 + i32.eqz + if + get_local $0 + get_local $1 + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/CharCode.DOT + get_global $~lib/internal/string/CharCode._0 + i32.const 16 + i32.shl + i32.or + i32.store offset=4 + get_local $1 + i32.const 2 + i32.add + return + end + get_local $1 + get_local $2 + i32.add + set_local $3 + get_local $1 + get_local $3 + i32.le_s + tee_local $4 + if (result i32) + get_local $3 + i32.const 21 + i32.le_s + else + get_local $4 + end + if + block $break|0 + get_local $1 + set_local $4 + loop $repeat|0 + get_local $4 + get_local $3 + i32.lt_s + i32.eqz + br_if $break|0 + get_local $0 + get_local $4 + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/CharCode._0 + i32.store16 offset=4 + get_local $4 + i32.const 1 + i32.add + set_local $4 + br $repeat|0 + unreachable + end + unreachable + end + get_local $0 + get_local $3 + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/CharCode.DOT + get_global $~lib/internal/string/CharCode._0 + i32.const 16 + i32.shl + i32.or + i32.store offset=4 + get_local $3 + i32.const 2 + i32.add + return + else + get_local $3 + i32.const 0 + i32.gt_s + tee_local $4 + if (result i32) + get_local $3 + i32.const 21 + i32.le_s + else + get_local $4 + end + if + get_local $0 + get_local $3 + i32.const 1 + i32.shl + i32.add + set_local $4 + get_local $4 + get_global $~lib/internal/string/HEADER_SIZE + i32.add + i32.const 2 + i32.add + set_local $5 + get_local $4 + get_global $~lib/internal/string/HEADER_SIZE + i32.add + set_local $6 + i32.const 0 + get_local $2 + i32.sub + i32.const 1 + i32.shl + set_local $7 + get_local $5 + get_local $6 + get_local $7 + call $~lib/internal/memory/memmove + get_local $0 + get_local $3 + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/CharCode.DOT + i32.store16 offset=4 + get_local $1 + i32.const 1 + i32.add + return + else + i32.const -6 + get_local $3 + i32.lt_s + tee_local $4 + if (result i32) + get_local $3 + i32.const 0 + i32.le_s + else + get_local $4 + end + if + i32.const 2 + get_local $3 + i32.sub + set_local $4 + get_local $0 + get_global $~lib/internal/string/HEADER_SIZE + i32.add + get_local $4 + i32.const 1 + i32.shl + i32.add + set_local $7 + get_local $0 + get_global $~lib/internal/string/HEADER_SIZE + i32.add + set_local $6 + get_local $1 + i32.const 1 + i32.shl + set_local $5 + get_local $7 + get_local $6 + get_local $5 + call $~lib/internal/memory/memmove + get_local $0 + get_global $~lib/internal/string/CharCode._0 + get_global $~lib/internal/string/CharCode.DOT + i32.const 16 + i32.shl + i32.or + i32.store offset=4 + block $break|1 + i32.const 2 + set_local $5 + loop $repeat|1 + get_local $5 + get_local $4 + i32.lt_s + i32.eqz + br_if $break|1 + get_local $0 + get_local $5 + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/CharCode._0 + i32.store16 offset=4 + get_local $5 + i32.const 1 + i32.add + set_local $5 + br $repeat|1 + unreachable + end + unreachable + end + get_local $1 + get_local $4 + i32.add + return + else + get_local $1 + i32.const 1 + i32.eq + if + get_local $0 + get_global $~lib/internal/string/CharCode.e + i32.store16 offset=6 + block $~lib/internal/number/genExponent|inlined.0 (result i32) + get_local $0 + i32.const 4 + i32.add + set_local $4 + get_local $3 + i32.const 1 + i32.sub + set_local $5 + get_local $5 + i32.const 0 + i32.lt_s + set_local $6 + get_local $6 + if + i32.const 0 + get_local $5 + i32.sub + set_local $5 + end + get_local $5 + call $~lib/internal/number/decimalCount32 + i32.const 1 + i32.add + set_local $7 + get_local $4 + get_local $5 + get_local $7 + call $~lib/internal/number/utoa32_lut + get_local $4 + get_global $~lib/internal/string/CharCode.MINUS + get_global $~lib/internal/string/CharCode.PLUS + get_local $6 + select + i32.store16 offset=4 + get_local $7 + end + set_local $1 + get_local $1 + i32.const 2 + i32.add + return + else + get_local $1 + i32.const 1 + i32.shl + set_local $7 + get_local $0 + get_global $~lib/internal/string/HEADER_SIZE + i32.add + i32.const 4 + i32.add + set_local $6 + get_local $0 + get_global $~lib/internal/string/HEADER_SIZE + i32.add + i32.const 2 + i32.add + set_local $5 + get_local $7 + i32.const 2 + i32.sub + set_local $4 + get_local $6 + get_local $5 + get_local $4 + call $~lib/internal/memory/memmove + get_local $0 + get_global $~lib/internal/string/CharCode.DOT + i32.store16 offset=6 + get_local $0 + get_local $7 + i32.add + get_global $~lib/internal/string/CharCode.e + i32.store16 offset=6 + get_local $1 + block $~lib/internal/number/genExponent|inlined.1 (result i32) + get_local $0 + get_local $7 + i32.add + i32.const 4 + i32.add + set_local $4 + get_local $3 + i32.const 1 + i32.sub + set_local $5 + get_local $5 + i32.const 0 + i32.lt_s + set_local $6 + get_local $6 + if + i32.const 0 + get_local $5 + i32.sub + set_local $5 + end + get_local $5 + call $~lib/internal/number/decimalCount32 + i32.const 1 + i32.add + set_local $8 + get_local $4 + get_local $5 + get_local $8 + call $~lib/internal/number/utoa32_lut + get_local $4 + get_global $~lib/internal/string/CharCode.MINUS + get_global $~lib/internal/string/CharCode.PLUS + get_local $6 + select + i32.store16 offset=4 + get_local $8 + end + i32.add + set_local $1 + get_local $1 + i32.const 2 + i32.add + return + end + unreachable + end + unreachable + end + unreachable + end + unreachable + unreachable + ) + (func $~lib/internal/number/dtoa_core (; 16 ;) (type $iFi) (param $0 i32) (param $1 f64) (result i32) + (local $2 i32) + (local $3 i64) + (local $4 i32) + (local $5 i64) + (local $6 i64) + (local $7 i64) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 f64) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i64) + (local $16 i64) + (local $17 i64) + (local $18 i64) + (local $19 i64) + (local $20 i64) + (local $21 i64) + (local $22 i64) + (local $23 i64) + (local $24 i64) + (local $25 i32) + get_local $1 + f64.const 0 + f64.lt + set_local $2 + get_local $2 + if + get_local $1 + f64.neg + set_local $1 + get_local $0 + get_global $~lib/internal/string/CharCode.MINUS + i32.store16 offset=4 + end + block $~lib/internal/number/grisu2|inlined.0 (result i32) + get_local $1 + i64.reinterpret/f64 + set_local $3 + get_local $3 + i64.const 9218868437227405312 + i64.and + i64.const 52 + i64.shr_u + i32.wrap/i64 + set_local $4 + get_local $3 + i64.const 4503599627370495 + i64.and + set_local $5 + get_local $4 + i32.const 0 + i32.ne + i64.extend_u/i32 + i64.const 52 + i64.shl + get_local $5 + i64.add + set_local $6 + get_local $4 + i32.const 1 + get_local $4 + i32.const 0 + i32.ne + select + i32.const 1023 + i32.const 52 + i32.add + i32.sub + set_local $4 + block + get_local $6 + i64.const 1 + i64.shl + i64.const 1 + i64.add + set_local $7 + get_local $4 + i32.const 1 + i32.sub + set_local $8 + get_local $7 + i64.clz + i32.wrap/i64 + set_local $9 + get_local $7 + get_local $9 + i64.extend_s/i32 + i64.shl + set_local $7 + get_local $8 + get_local $9 + i32.sub + set_local $8 + i32.const 1 + get_local $6 + i64.const 4503599627370496 + i64.eq + i32.add + set_local $10 + get_local $7 + set_global $~lib/internal/number/_frc_plus + get_local $6 + get_local $10 + i64.extend_s/i32 + i64.shl + i64.const 1 + i64.sub + get_local $4 + get_local $10 + i32.sub + get_local $8 + i32.sub + i64.extend_s/i32 + i64.shl + set_global $~lib/internal/number/_frc_minus + get_local $8 + set_global $~lib/internal/number/_exp + end + block + get_global $~lib/internal/number/_exp + set_local $10 + i32.const -61 + get_local $10 + i32.sub + f64.convert_s/i32 + f64.const 0.30102999566398114 + f64.mul + f64.const 347 + f64.add + set_local $11 + get_local $11 + i32.trunc_s/f64 + set_local $9 + get_local $9 + get_local $9 + f64.convert_s/i32 + get_local $11 + f64.ne + i32.add + set_local $9 + get_local $9 + i32.const 3 + i32.shr_s + i32.const 1 + i32.add + set_local $8 + i32.const 348 + get_local $8 + i32.const 3 + i32.shl + i32.sub + set_global $~lib/internal/number/_K + block $~lib/internal/number/FRC_POWERS|inlined.0 (result i32) + i32.const 1728 + end + i32.load + set_local $12 + block $~lib/internal/number/EXP_POWERS|inlined.0 (result i32) + i32.const 1992 + end + i32.load + set_local $13 + block $~lib/internal/arraybuffer/LOAD|inlined.0 (result i64) + i32.const 0 + set_local $14 + get_local $12 + get_local $8 + i32.const 3 + i32.shl + i32.add + get_local $14 + i32.add + i64.load offset=8 + end + set_global $~lib/internal/number/_frc_pow + block $~lib/internal/arraybuffer/LOAD|inlined.0 (result i32) + i32.const 0 + set_local $14 + get_local $13 + get_local $8 + i32.const 1 + i32.shl + i32.add + get_local $14 + i32.add + i32.load16_s offset=8 + end + set_global $~lib/internal/number/_exp_pow + end + get_local $6 + i64.clz + i32.wrap/i64 + set_local $13 + get_local $6 + get_local $13 + i64.extend_s/i32 + i64.shl + set_local $6 + get_local $4 + get_local $13 + i32.sub + set_local $4 + get_global $~lib/internal/number/_frc_pow + set_local $7 + get_global $~lib/internal/number/_exp_pow + set_local $12 + block $~lib/internal/number/umul64f|inlined.0 (result i64) + get_local $6 + i64.const 4294967295 + i64.and + set_local $15 + get_local $7 + i64.const 4294967295 + i64.and + set_local $16 + get_local $6 + i64.const 32 + i64.shr_u + set_local $17 + get_local $7 + i64.const 32 + i64.shr_u + set_local $18 + get_local $15 + get_local $16 + i64.mul + set_local $19 + get_local $17 + get_local $16 + i64.mul + get_local $19 + i64.const 32 + i64.shr_u + i64.add + set_local $20 + get_local $15 + get_local $18 + i64.mul + get_local $20 + i64.const 4294967295 + i64.and + i64.add + set_local $21 + get_local $21 + i64.const 2147483647 + i64.add + set_local $21 + get_local $20 + i64.const 32 + i64.shr_u + set_local $20 + get_local $21 + i64.const 32 + i64.shr_u + set_local $21 + get_local $17 + get_local $18 + i64.mul + get_local $20 + i64.add + get_local $21 + i64.add + end + set_local $21 + block $~lib/internal/number/umul64e|inlined.0 (result i32) + get_local $4 + get_local $12 + i32.add + i32.const 64 + i32.add + end + set_local $8 + block $~lib/internal/number/umul64f|inlined.1 (result i64) + get_global $~lib/internal/number/_frc_plus + set_local $20 + get_local $20 + i64.const 4294967295 + i64.and + set_local $19 + get_local $7 + i64.const 4294967295 + i64.and + set_local $18 + get_local $20 + i64.const 32 + i64.shr_u + set_local $17 + get_local $7 + i64.const 32 + i64.shr_u + set_local $16 + get_local $19 + get_local $18 + i64.mul + set_local $15 + get_local $17 + get_local $18 + i64.mul + get_local $15 + i64.const 32 + i64.shr_u + i64.add + set_local $22 + get_local $19 + get_local $16 + i64.mul + get_local $22 + i64.const 4294967295 + i64.and + i64.add + set_local $23 + get_local $23 + i64.const 2147483647 + i64.add + set_local $23 + get_local $22 + i64.const 32 + i64.shr_u + set_local $22 + get_local $23 + i64.const 32 + i64.shr_u + set_local $23 + get_local $17 + get_local $16 + i64.mul + get_local $22 + i64.add + get_local $23 + i64.add + end + i64.const 1 + i64.sub + set_local $23 + block $~lib/internal/number/umul64e|inlined.1 (result i32) + get_global $~lib/internal/number/_exp + set_local $9 + get_local $9 + get_local $12 + i32.add + i32.const 64 + i32.add + end + set_local $9 + block $~lib/internal/number/umul64f|inlined.2 (result i64) + get_global $~lib/internal/number/_frc_minus + set_local $22 + get_local $22 + i64.const 4294967295 + i64.and + set_local $15 + get_local $7 + i64.const 4294967295 + i64.and + set_local $16 + get_local $22 + i64.const 32 + i64.shr_u + set_local $17 + get_local $7 + i64.const 32 + i64.shr_u + set_local $18 + get_local $15 + get_local $16 + i64.mul + set_local $19 + get_local $17 + get_local $16 + i64.mul + get_local $19 + i64.const 32 + i64.shr_u + i64.add + set_local $20 + get_local $15 + get_local $18 + i64.mul + get_local $20 + i64.const 4294967295 + i64.and + i64.add + set_local $24 + get_local $24 + i64.const 2147483647 + i64.add + set_local $24 + get_local $20 + i64.const 32 + i64.shr_u + set_local $20 + get_local $24 + i64.const 32 + i64.shr_u + set_local $24 + get_local $17 + get_local $18 + i64.mul + get_local $20 + i64.add + get_local $24 + i64.add + end + i64.const 1 + i64.add + set_local $24 + get_local $23 + get_local $24 + i64.sub + set_local $20 + get_local $0 + get_local $21 + get_local $8 + get_local $23 + get_local $9 + get_local $20 + get_local $2 + call $~lib/internal/number/genDigits + end + set_local $25 + get_local $0 + get_local $2 + i32.const 1 + i32.shl + i32.add + get_local $25 + get_local $2 + i32.sub + get_global $~lib/internal/number/_K + call $~lib/internal/number/prettify + set_local $25 + get_local $25 + get_local $2 + i32.add + ) + (func $~lib/internal/string/copyUnsafe (; 17 ;) (type $iiiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + get_local $0 + get_local $1 + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/HEADER_SIZE + i32.add + set_local $5 + get_local $2 + get_local $3 + i32.const 1 + i32.shl + i32.add + get_global $~lib/internal/string/HEADER_SIZE + i32.add + set_local $6 + get_local $4 + i32.const 1 + i32.shl + set_local $7 + get_local $5 + get_local $6 + get_local $7 + call $~lib/internal/memory/memmove + ) + (func $~lib/string/String#substring (; 18 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + get_local $0 + i32.const 0 + i32.ne + i32.eqz + if + i32.const 0 + i32.const 2072 + i32.const 269 + i32.const 4 + call $~lib/env/abort + unreachable + end + get_local $0 + i32.load + set_local $3 + get_local $1 + tee_local $4 + i32.const 0 + tee_local $5 + get_local $4 + get_local $5 + i32.gt_s + select + tee_local $4 + get_local $3 + tee_local $5 + get_local $4 + get_local $5 + i32.lt_s + select + set_local $6 + get_local $2 + tee_local $4 + i32.const 0 + tee_local $5 + get_local $4 + get_local $5 + i32.gt_s + select + tee_local $4 + get_local $3 + tee_local $5 + get_local $4 + get_local $5 + i32.lt_s + select + set_local $7 + get_local $6 + tee_local $4 + get_local $7 + tee_local $5 + get_local $4 + get_local $5 + i32.lt_s + select + set_local $8 + get_local $6 + tee_local $4 + get_local $7 + tee_local $5 + get_local $4 + get_local $5 + i32.gt_s + select + set_local $9 + get_local $9 + get_local $8 + i32.sub + set_local $3 + get_local $3 + i32.eqz + if + i32.const 2104 + return + end + get_local $8 + i32.eqz + tee_local $4 + if (result i32) + get_local $9 + get_local $0 + i32.load + i32.eq + else + get_local $4 + end + if + get_local $0 + return + end + get_local $3 + call $~lib/internal/string/allocateUnsafe + set_local $10 + get_local $10 + i32.const 0 + get_local $0 + get_local $8 + get_local $3 + call $~lib/internal/string/copyUnsafe + get_local $10 + ) + (func $~lib/allocator/arena/__memory_free (; 19 ;) (type $iv) (param $0 i32) + nop + ) + (func $~lib/internal/number/dtoa (; 20 ;) (type $Fi) (param $0 f64) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + get_local $0 + f64.const 0 + f64.eq + if + i32.const 624 + return + end + get_local $0 + call $~lib/builtins/isFinite + i32.eqz + if + get_local $0 + call $~lib/builtins/isNaN + if + i32.const 640 + return + end + i32.const 656 + i32.const 680 + get_local $0 + f64.const 0 + f64.lt + select + return + end + get_global $~lib/internal/number/MAX_DOUBLE_LENGTH + call $~lib/internal/string/allocateUnsafe + set_local $1 + get_local $1 + get_local $0 + call $~lib/internal/number/dtoa_core + set_local $2 + get_local $1 + i32.const 0 + get_local $2 + call $~lib/string/String#substring + set_local $3 + get_local $1 + i32.eqz + if + i32.const 0 + i32.const 16 + i32.const 28 + i32.const 4 + call $~lib/env/abort + unreachable + end + block $~lib/memory/memory.free|inlined.0 + block + get_local $1 + call $~lib/allocator/arena/__memory_free + br $~lib/memory/memory.free|inlined.0 + unreachable + end + unreachable + end + get_local $3 + ) + (func $~lib/number/F64#toString (; 21 ;) (type $Fi) (param $0 f64) (result i32) + get_local $0 + call $~lib/internal/number/dtoa + ) + (func $~lib/number/Bool#toString (; 22 ;) (type $ii) (param $0 i32) (result i32) + get_local $0 + i32.const 0 + i32.ne + if (result i32) + i32.const 2160 + else + i32.const 2176 + end + ) + (func $~lib/number/F32.isSafeInteger (; 23 ;) (type $fi) (param $0 f32) (result i32) + (local $1 i32) + get_local $0 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $1 + if (result i32) + get_local $0 + f32.trunc + get_local $0 + f32.eq + else + get_local $1 + end + ) + (func $~lib/number/F32.isInteger (; 24 ;) (type $fi) (param $0 f32) (result i32) + (local $1 i32) + block $~lib/builtins/isFinite|inlined.0 (result i32) + get_local $0 + get_local $0 + f32.sub + f32.const 0 + f32.eq + end + tee_local $1 + i32.const 0 + i32.ne + if (result i32) + get_local $0 + f32.trunc + get_local $0 + f32.eq + else + get_local $1 + end + ) + (func $~lib/number/F64.isSafeInteger (; 25 ;) (type $Fi) (param $0 f64) (result i32) + (local $1 i32) + get_local $0 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $1 + if (result i32) + get_local $0 + f64.trunc + get_local $0 + f64.eq + else + get_local $1 + end + ) + (func $~lib/number/F64.isInteger (; 26 ;) (type $Fi) (param $0 f64) (result i32) + (local $1 i32) + block $~lib/builtins/isFinite|inlined.0 (result i32) + get_local $0 + get_local $0 + f64.sub + f64.const 0 + f64.eq + end + tee_local $1 + i32.const 0 + i32.ne + if (result i32) + get_local $0 + f64.trunc + get_local $0 + f64.eq + else + get_local $1 + end + ) + (func $start (; 27 ;) (type $v) + (local $0 i32) + (local $1 f32) + (local $2 f64) + get_global $HEAP_BASE + get_global $~lib/internal/allocator/AL_MASK + i32.add + get_global $~lib/internal/allocator/AL_MASK + i32.const -1 + i32.xor + i32.and + set_global $~lib/allocator/arena/startOffset + get_global $~lib/allocator/arena/startOffset + set_global $~lib/allocator/arena/offset + get_global $number/a + call $~lib/number/I32#toString + i32.const 592 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 7 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const 2 + call $~lib/number/F64#toString + i32.const 2112 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 9 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 3 + call $~lib/number/I32#toString + i32.const 2128 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 10 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const -5 + call $~lib/number/I32#toString + i32.const 2136 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 12 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 4 + call $~lib/number/I32#toString + i32.const 2144 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 13 + i32.const 0 + call $~lib/env/abort + unreachable + end + block (result i32) + get_global $number/a + i32.const 1 + i32.add + set_global $number/a + get_global $number/a + end + call $~lib/number/I32#toString + i32.const 2152 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 14 + i32.const 0 + call $~lib/env/abort + unreachable + end + block (result i32) + get_global $number/a + i32.const 1 + i32.sub + set_global $number/a + get_global $number/a + end + call $~lib/number/I32#toString + i32.const 592 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 15 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 0 + i32.eqz + call $~lib/number/Bool#toString + i32.const 2160 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 16 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 1 + i32.eqz + call $~lib/number/Bool#toString + i32.const 2176 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 17 + i32.const 0 + call $~lib/env/abort + unreachable + end + block (result i32) + get_global $number/a + tee_local $0 + i32.const 1 + i32.add + set_global $number/a + get_local $0 + end + call $~lib/number/I32#toString + i32.const 592 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 20 + i32.const 0 + call $~lib/env/abort + unreachable + end + block (result i32) + get_global $number/a + tee_local $0 + i32.const 1 + i32.sub + set_global $number/a + get_local $0 + end + call $~lib/number/I32#toString + i32.const 2152 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 21 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/isNaN|inlined.0 (result i32) + get_global $~lib/number/F32.NaN + set_local $1 + get_local $1 + get_local $1 + f32.ne + end + i32.const 0 + i32.ne + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 25 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f32.MIN_SAFE_INTEGER + f32.const 1 + f32.sub + call $~lib/number/F32.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 27 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f32.MIN_SAFE_INTEGER + call $~lib/number/F32.isSafeInteger + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 28 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const 0 + call $~lib/number/F32.isSafeInteger + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 29 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const -0 + call $~lib/number/F32.isSafeInteger + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 30 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const nan:0x400000 + call $~lib/number/F32.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 31 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const inf + call $~lib/number/F32.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 32 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + call $~lib/number/F32.isSafeInteger + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 33 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.const 1 + f32.add + call $~lib/number/F32.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 34 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const 0.5 + call $~lib/number/F32.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 35 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const 0 + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 36 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const -0 + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 37 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const nan:0x400000 + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 38 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const inf + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 39 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f32.EPSILON + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 40 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const 1 + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 41 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const -1 + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 42 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f32.MIN_SAFE_INTEGER + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 43 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 44 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const 0.5 + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 45 + i32.const 0 + call $~lib/env/abort + unreachable + end + f32.const -1.5 + call $~lib/number/F32.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 46 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/isNaN|inlined.0 (result i32) + get_global $~lib/number/F64.NaN + set_local $2 + get_local $2 + get_local $2 + f64.ne + end + i32.const 0 + i32.ne + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 48 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f64.MIN_SAFE_INTEGER + f64.const 1 + f64.sub + call $~lib/number/F64.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 50 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f64.MIN_SAFE_INTEGER + call $~lib/number/F64.isSafeInteger + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 51 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const 0 + call $~lib/number/F64.isSafeInteger + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 52 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const -0 + call $~lib/number/F64.isSafeInteger + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 53 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const nan:0x8000000000000 + call $~lib/number/F64.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 54 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const inf + call $~lib/number/F64.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 55 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + call $~lib/number/F64.isSafeInteger + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 56 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.const 1 + f64.add + call $~lib/number/F64.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 57 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const 0.5 + call $~lib/number/F64.isSafeInteger + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 58 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const 0 + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 59 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const -0 + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 60 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const nan:0x8000000000000 + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 61 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const inf + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 62 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f64.EPSILON + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 63 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const 1 + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 64 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const -1 + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 65 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f64.MIN_SAFE_INTEGER + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 66 + i32.const 0 + call $~lib/env/abort + unreachable + end + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 67 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const 0.5 + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 68 + i32.const 0 + call $~lib/env/abort + unreachable + end + f64.const -1.5 + call $~lib/number/F64.isInteger + i32.const 0 + i32.ne + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 600 + i32.const 69 + i32.const 0 + call $~lib/env/abort + unreachable + end + ) + (func $null (; 28 ;) (type $v) + ) +)