Implement optional type parameters (#360)

* Add a NATIVE<T> macro type to simplify use of a native WebAssembly type
* Add default type parameters for internal helpers for explicit loads and stores
* Unify loadUnsafe/loadUnsafeWithOffset etc. into one
* Renamed loadUnsafe etc. into just LOAD, like a macro
* Implement parsing of index signatures, but ignore them, for properly linting code
* Refactor TypedArray<T> to use macros
This commit is contained in:
Daniel Wirtz 2018-12-07 14:33:32 +01:00 committed by GitHub
parent d7f4874650
commit ebae7cbd73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 4698 additions and 4128 deletions

View File

@ -87,6 +87,7 @@ export enum NodeKind {
FIELDDECLARATION,
FUNCTIONDECLARATION,
IMPORTDECLARATION,
INDEXSIGNATUREDECLARATION,
INTERFACEDECLARATION,
METHODDECLARATION,
NAMESPACEDECLARATION,
@ -181,12 +182,14 @@ export abstract class Node {
static createTypeParameter(
name: IdentifierExpression,
extendsType: TypeNode | null,
defaultType: TypeNode | null,
range: Range
): TypeParameterNode {
var elem = new TypeParameterNode();
elem.range = range;
elem.name = name; name.parent = elem;
elem.extendsType = extendsType; if (extendsType) extendsType.parent = elem;
elem.defaultType = defaultType; if (defaultType) defaultType.parent = elem;
return elem;
}
@ -871,6 +874,18 @@ export abstract class Node {
return stmt;
}
static createIndexSignatureDeclaration(
keyType: TypeNode,
valueType: CommonTypeNode,
range: Range
): IndexSignatureDeclaration {
var elem = new IndexSignatureDeclaration();
elem.range = range;
elem.keyType = keyType; keyType.parent = elem;
elem.valueType = valueType; valueType.parent = elem;
return elem;
}
static createMethodDeclaration(
name: IdentifierExpression,
typeParameters: TypeParameterNode[] | null,
@ -1070,6 +1085,8 @@ export class TypeParameterNode extends Node {
name: IdentifierExpression;
/** Extended type reference, if any. */
extendsType: TypeNode | null; // can't be a function
/** Default type if omitted, if any. */
defaultType: TypeNode | null; // can't be a function
}
/** Represents the kind of a parameter. */
@ -1622,6 +1639,16 @@ export abstract class DeclarationStatement extends Statement {
}
}
/** Represents an index signature declaration. */
export class IndexSignatureDeclaration extends DeclarationStatement {
kind = NodeKind.INDEXSIGNATUREDECLARATION;
/** Key type. */
keyType: TypeNode;
/** Value type. */
valueType: CommonTypeNode;
}
/** Base class of all variable-like declaration statements. */
export abstract class VariableLikeDeclarationStatement extends DeclarationStatement {

View File

@ -162,7 +162,8 @@ import {
writeI32,
writeI64,
writeF32,
writeF64
writeF64,
makeMap
} from "./util";
/** Compilation target. */
@ -619,7 +620,7 @@ export class Compiler extends DiagnosticEmitter {
(noTreeShaking || (isEntry && statement.is(CommonFlags.EXPORT))) &&
!(<ClassDeclaration>statement).isGeneric
) {
this.compileClassDeclaration(<ClassDeclaration>statement, [], null);
this.compileClassDeclaration(<ClassDeclaration>statement, []);
}
break;
}
@ -958,16 +959,15 @@ export class Compiler extends DiagnosticEmitter {
/** Compiles a top-level function given its declaration. */
compileFunctionDeclaration(
declaration: FunctionDeclaration,
typeArguments: TypeNode[],
contextualTypeArguments: Map<string,Type> | null = null
typeArguments: TypeNode[]
): Function | null {
var element = assert(this.program.elementsLookup.get(declaration.fileLevelInternalName));
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
return this.compileFunctionUsingTypeArguments( // reports
<FunctionPrototype>element,
typeArguments,
contextualTypeArguments,
null, // no outer scope (is top level)
makeMap<string,Type>(),
null,
(<FunctionPrototype>element).declaration.name
);
}
@ -976,7 +976,7 @@ export class Compiler extends DiagnosticEmitter {
compileFunctionUsingTypeArguments(
prototype: FunctionPrototype,
typeArguments: TypeNode[],
contextualTypeArguments: Map<string,Type> | null,
contextualTypeArguments: Map<string,Type>,
outerScope: Flow | null,
reportNode: Node
): Function | null {
@ -1234,7 +1234,11 @@ export class Compiler extends DiagnosticEmitter {
(<ClassPrototype>element).is(CommonFlags.EXPORT)
) && !(<ClassPrototype>element).is(CommonFlags.GENERIC)
) {
this.compileClassUsingTypeArguments(<ClassPrototype>element, []);
this.compileClassUsingTypeArguments(
<ClassPrototype>element,
[],
makeMap<string,Type>()
);
}
break;
}
@ -1252,8 +1256,8 @@ export class Compiler extends DiagnosticEmitter {
this.compileFunctionUsingTypeArguments(
<FunctionPrototype>element,
[],
null, // no contextual type arguments
null, // no outer scope
makeMap<string,Type>(),
null,
(<FunctionPrototype>element).declaration.name
);
}
@ -1286,7 +1290,11 @@ export class Compiler extends DiagnosticEmitter {
switch (element.kind) {
case ElementKind.CLASS_PROTOTYPE: {
if (!(<ClassPrototype>element).is(CommonFlags.GENERIC)) {
this.compileClassUsingTypeArguments(<ClassPrototype>element, []);
this.compileClassUsingTypeArguments(
<ClassPrototype>element,
[],
makeMap<string,Type>()
);
}
break;
}
@ -1302,8 +1310,8 @@ export class Compiler extends DiagnosticEmitter {
this.compileFunctionUsingTypeArguments(
<FunctionPrototype>element,
[],
null, // no contextual type arguments
null, // no outer scope
makeMap<string,Type>(),
null,
(<FunctionPrototype>element).declaration.name
);
}
@ -1325,15 +1333,14 @@ export class Compiler extends DiagnosticEmitter {
compileClassDeclaration(
declaration: ClassDeclaration,
typeArguments: TypeNode[],
contextualTypeArguments: Map<string,Type> | null = null
typeArguments: TypeNode[]
): void {
var element = assert(this.program.elementsLookup.get(declaration.fileLevelInternalName));
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
this.compileClassUsingTypeArguments(
<ClassPrototype>element,
typeArguments,
contextualTypeArguments,
makeMap<string,Type>(),
declaration
);
}
@ -1341,7 +1348,7 @@ export class Compiler extends DiagnosticEmitter {
compileClassUsingTypeArguments(
prototype: ClassPrototype,
typeArguments: TypeNode[],
contextualTypeArguments: Map<string,Type> | null = null,
contextualTypeArguments: Map<string,Type>,
alternativeReportNode: Node | null = null
): void {
var instance = this.resolver.resolveClassInclTypeArguments(
@ -1372,7 +1379,9 @@ export class Compiler extends DiagnosticEmitter {
) {
this.compileFunctionUsingTypeArguments(
<FunctionPrototype>element,
[], null, null,
[],
makeMap<string,Type>(),
null,
(<FunctionPrototype>element).declaration.name
);
}
@ -1383,7 +1392,9 @@ export class Compiler extends DiagnosticEmitter {
if (getter) {
this.compileFunctionUsingTypeArguments(
getter,
[], null, null,
[],
makeMap<string,Type>(),
null,
getter.declaration.name
);
}
@ -1391,7 +1402,9 @@ export class Compiler extends DiagnosticEmitter {
if (setter) {
this.compileFunctionUsingTypeArguments(
setter,
[], null, null,
[],
makeMap<string,Type>(),
null,
setter.declaration.name
);
}
@ -1413,8 +1426,8 @@ export class Compiler extends DiagnosticEmitter {
this.compileFunctionUsingTypeArguments(
<FunctionPrototype>element,
[],
instance.contextualTypeArguments,
null, // no outer scope
makeMap<string,Type>(instance.contextualTypeArguments),
null,
(<FunctionPrototype>element).declaration.name
);
}
@ -1429,7 +1442,9 @@ export class Compiler extends DiagnosticEmitter {
if (getter) {
this.compileFunctionUsingTypeArguments(
getter,
[], instance.contextualTypeArguments, null,
[],
makeMap<string,Type>(instance.contextualTypeArguments),
null,
getter.declaration.name
);
}
@ -1437,7 +1452,9 @@ export class Compiler extends DiagnosticEmitter {
if (setter) {
this.compileFunctionUsingTypeArguments(
setter,
[], instance.contextualTypeArguments, null,
[],
makeMap<string,Type>(instance.contextualTypeArguments),
null,
setter.declaration.name
);
}
@ -5014,7 +5031,7 @@ export class Compiler extends DiagnosticEmitter {
instance = this.resolver.resolveFunctionInclTypeArguments(
prototype,
typeArguments,
this.currentFunction.flow.contextualTypeArguments,
makeMap<string,Type>(this.currentFunction.flow.contextualTypeArguments),
expression
);
@ -5088,7 +5105,7 @@ export class Compiler extends DiagnosticEmitter {
instance = this.resolver.resolveFunction(
prototype,
resolvedTypeArguments,
this.currentFunction.flow.contextualTypeArguments
makeMap<string,Type>(this.currentFunction.flow.contextualTypeArguments)
);
if (!instance) return this.module.createUnreachable();
return this.makeCallDirect(instance, argumentExprs);
@ -5098,11 +5115,7 @@ export class Compiler extends DiagnosticEmitter {
// otherwise resolve the non-generic call as usual
} else {
instance = this.resolver.resolveFunction(
prototype,
null,
this.currentFunction.flow.contextualTypeArguments
);
instance = this.resolver.resolveFunction(prototype, null);
}
if (!instance) return this.module.createUnreachable();
@ -5241,7 +5254,7 @@ export class Compiler extends DiagnosticEmitter {
typeArguments = this.resolver.resolveTypeArguments(
assert(prototype.declaration.typeParameters),
typeArgumentNodes,
this.currentFunction.flow.contextualTypeArguments,
makeMap<string,Type>(this.currentFunction.flow.contextualTypeArguments),
expression
);
}
@ -5932,7 +5945,7 @@ export class Compiler extends DiagnosticEmitter {
var instance = this.compileFunctionUsingTypeArguments(
prototype,
[],
flow.contextualTypeArguments,
makeMap<string,Type>(flow.contextualTypeArguments),
flow,
declaration
);
@ -6093,7 +6106,7 @@ export class Compiler extends DiagnosticEmitter {
let instance = this.resolver.resolveFunction(
<FunctionPrototype>target,
null,
currentFunction.flow.contextualTypeArguments
makeMap<string,Type>(currentFunction.flow.contextualTypeArguments)
);
if (!(instance && this.compileFunction(instance))) return module.createUnreachable();
let index = this.ensureFunctionTableEntry(instance);
@ -6438,7 +6451,11 @@ export class Compiler extends DiagnosticEmitter {
// create the Array segment and return a pointer to it
var arrayPrototype = assert(program.arrayPrototype);
var arrayInstance = assert(this.resolver.resolveClass(arrayPrototype, [ elementType ]));
var arrayInstance = assert(this.resolver.resolveClass(
arrayPrototype,
[ elementType ],
makeMap<string,Type>()
));
var arrayHeaderSize = (arrayInstance.currentMemoryOffset + 7) & ~7;
if (hasGC) {
buf = new Uint8Array(gcHeaderSize + arrayHeaderSize);
@ -6506,9 +6523,11 @@ export class Compiler extends DiagnosticEmitter {
// otherwise obtain the array type
var arrayPrototype = assert(this.program.arrayPrototype);
if (!arrayPrototype || arrayPrototype.kind != ElementKind.CLASS_PROTOTYPE) return module.createUnreachable();
var arrayInstance = this.resolver.resolveClass(<ClassPrototype>arrayPrototype, [ elementType ]);
if (!arrayInstance) return module.createUnreachable();
var arrayInstance = assert(this.resolver.resolveClass(
<ClassPrototype>arrayPrototype,
[ elementType ],
makeMap<string,Type>()
));
var arrayType = arrayInstance.type;
// and compile an explicit instantiation
@ -6660,13 +6679,13 @@ export class Compiler extends DiagnosticEmitter {
classInstance = this.resolver.resolveClass(
classPrototype,
classReference.typeArguments,
currentFunction.flow.contextualTypeArguments
makeMap<string,Type>(currentFunction.flow.contextualTypeArguments)
);
} else {
classInstance = this.resolver.resolveClassInclTypeArguments(
classPrototype,
typeArguments,
currentFunction.flow.contextualTypeArguments,
makeMap<string,Type>(currentFunction.flow.contextualTypeArguments),
expression
);
}

View File

@ -121,6 +121,7 @@ export enum DiagnosticCode {
Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration = 2673,
Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration = 2674,
Namespace_0_has_no_exported_member_1 = 2694,
Required_type_parameters_may_not_follow_optional_type_parameters = 2706,
File_0_not_found = 6054,
Numeric_separators_are_not_allowed_here = 6188,
Multiple_consecutive_numeric_separators_are_not_permitted = 6189
@ -243,6 +244,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 2673: return "Constructor of class '{0}' is private and only accessible within the class declaration.";
case 2674: return "Constructor of class '{0}' is protected and only accessible within the class declaration.";
case 2694: return "Namespace '{0}' has no exported member '{1}'.";
case 2706: return "Required type parameters may not follow optional type parameters.";
case 6054: return "File '{0}' not found.";
case 6188: return "Numeric separators are not allowed here.";
case 6189: return "Multiple consecutive numeric separators are not permitted.";

View File

@ -115,6 +115,7 @@
"Constructor of class '{0}' is private and only accessible within the class declaration.": 2673,
"Constructor of class '{0}' is protected and only accessible within the class declaration.": 2674,
"Namespace '{0}' has no exported member '{1}'.": 2694,
"Required type parameters may not follow optional type parameters.": 2706,
"File '{0}' not found.": 6054,
"Numeric separators are not allowed here.": 6188,

View File

@ -68,6 +68,7 @@ import {
FieldDeclaration,
FunctionDeclaration,
ImportDeclaration,
IndexSignatureDeclaration,
InterfaceDeclaration,
MethodDeclaration,
NamespaceDeclaration,
@ -295,6 +296,10 @@ export class ASTBuilder {
this.visitImportDeclaration(<ImportDeclaration>node);
break;
}
case NodeKind.INDEXSIGNATUREDECLARATION: {
this.visitIndexSignatureDeclaration(<IndexSignatureDeclaration>node);
break;
}
case NodeKind.INTERFACEDECLARATION: {
this.visitInterfaceDeclaration(<InterfaceDeclaration>node);
break;
@ -379,6 +384,11 @@ export class ASTBuilder {
this.sb.push(" extends ");
this.visitTypeNode(extendsType);
}
var defaultType = node.defaultType;
if (defaultType) {
this.sb.push("=");
this.visitTypeNode(defaultType);
}
}
visitSignatureNode(node: SignatureNode): void {
@ -1176,6 +1186,14 @@ export class ASTBuilder {
this.visitStringLiteralExpression(node.path);
}
visitIndexSignatureDeclaration(node: IndexSignatureDeclaration): void {
var sb = this.sb;
sb.push("[key: ");
this.visitTypeNode(node.keyType);
sb.push("]: ");
this.visitTypeNode(node.valueType);
}
visitInterfaceDeclaration(node: InterfaceDeclaration): void {
var decorators = node.decorators;
if (decorators) {

View File

@ -83,7 +83,8 @@ import {
mangleInternalPath,
nodeIsCallable,
nodeIsGenericCallable
nodeIsGenericCallable,
IndexSignatureDeclaration
} from "./ast";
/** Parser interface. */
@ -926,9 +927,19 @@ export class Parser extends DiagnosticEmitter {
// at '<': TypeParameter (',' TypeParameter)* '>'
var typeParameters = new Array<TypeParameterNode>();
var seenOptional = false;
while (!tn.skip(Token.GREATERTHAN)) {
let typeParameter = this.parseTypeParameter(tn);
if (!typeParameter) return null;
if (typeParameter.defaultType !== null) {
seenOptional = true;
} else if (seenOptional) {
this.error(
DiagnosticCode.Required_type_parameters_may_not_follow_optional_type_parameters,
typeParameter.range
);
typeParameter.defaultType = null;
}
typeParameters.push(<TypeParameterNode>typeParameter);
if (!tn.skip(Token.COMMA)) {
if (tn.skip(Token.GREATERTHAN)) {
@ -955,7 +966,7 @@ export class Parser extends DiagnosticEmitter {
tn: Tokenizer
): TypeParameterNode | null {
// before: Identifier ('extends' Type)?
// before: Identifier ('extends' Type)? ('=' Type)?
if (tn.next() == Token.IDENTIFIER) {
let identifier = Node.createIdentifierExpression(
@ -975,9 +986,23 @@ export class Parser extends DiagnosticEmitter {
}
extendsType = <TypeNode>t;
}
let defaultType: TypeNode | null = null;
if (tn.skip(Token.EQUALS)) {
let t = this.parseType(tn);
if (!t) return null;
if (t.kind != NodeKind.TYPE) {
this.error(
DiagnosticCode.Operation_not_supported,
t.range
);
return null;
}
defaultType = <TypeNode>t;
}
return Node.createTypeParameter(
identifier,
extendsType,
defaultType,
Range.join(identifier.range, tn.range())
);
} else {
@ -1602,16 +1627,18 @@ export class Parser extends DiagnosticEmitter {
var isInterface = parent.kind == NodeKind.INTERFACEDECLARATION;
var decorators = new Array<DecoratorNode>();
while (tn.skip(Token.AT)) {
let decorator = this.parseDecorator(tn);
if (!decorator) break;
if (tn.skip(Token.AT)) {
do {
let decorator = this.parseDecorator(tn);
if (!decorator) break;
decorators.push(<DecoratorNode>decorator);
} while (tn.skip(Token.AT));
if (isInterface) {
this.error(
DiagnosticCode.Decorators_are_not_valid_here,
decorator.range
Range.join(decorators[0].range, decorators[decorators.length - 1].range)
);
}
decorators.push(<DecoratorNode>decorator);
}
// inherit ambient status
@ -1620,6 +1647,8 @@ export class Parser extends DiagnosticEmitter {
// implemented methods are virtual
if (isInterface) flags |= CommonFlags.VIRTUAL;
var accessStart = 0;
var accessEnd = 0;
if (tn.skip(Token.PUBLIC)) {
if (isInterface) {
this.error(
@ -1628,6 +1657,8 @@ export class Parser extends DiagnosticEmitter {
);
}
flags |= CommonFlags.PUBLIC;
accessStart = tn.tokenPos;
accessEnd = tn.pos;
} else if (tn.skip(Token.PRIVATE)) {
if (isInterface) {
this.error(
@ -1636,6 +1667,8 @@ export class Parser extends DiagnosticEmitter {
);
}
flags |= CommonFlags.PRIVATE;
accessStart = tn.tokenPos;
accessEnd = tn.pos;
} else if (tn.skip(Token.PROTECTED)) {
if (isInterface) {
this.error(
@ -1644,12 +1677,14 @@ export class Parser extends DiagnosticEmitter {
);
}
flags |= CommonFlags.PROTECTED;
accessStart = tn.tokenPos;
accessEnd = tn.pos;
}
var staticStart: i32 = 0;
var staticEnd: i32 = 0;
var abstractStart: i32 = 0;
var abstractEnd: i32 = 0;
var staticStart = 0;
var staticEnd = 0;
var abstractStart = 0;
var abstractEnd = 0;
if (tn.skip(Token.STATIC)) {
if (isInterface) {
this.error(
@ -1673,9 +1708,7 @@ export class Parser extends DiagnosticEmitter {
abstractStart = tn.tokenPos;
abstractEnd = tn.pos;
}
if (parent.flags & CommonFlags.GENERIC) {
flags |= CommonFlags.GENERIC_CONTEXT;
}
if (parent.flags & CommonFlags.GENERIC) flags |= CommonFlags.GENERIC_CONTEXT;
}
var readonlyStart: i32 = 0;
@ -1713,7 +1746,7 @@ export class Parser extends DiagnosticEmitter {
}
} else if (tn.skip(Token.SET)) {
if (tn.peek(true, IdentifierHandling.PREFER) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
flags |= CommonFlags.SET | CommonFlags.SET;
flags |= CommonFlags.SET;
isSetter = true;
setStart = tn.tokenPos;
setEnd = tn.pos;
@ -1750,17 +1783,60 @@ export class Parser extends DiagnosticEmitter {
}
}
if (!isConstructor && !tn.skipIdentifier()) {
this.error(
DiagnosticCode.Identifier_expected,
tn.range()
);
return null;
var name: IdentifierExpression;
if (isConstructor) {
name = Node.createConstructorExpression(tn.range());
} else {
if (!(isGetter || isSetter) && tn.skip(Token.OPENBRACKET)) {
// TODO: also handle symbols, which might have some of these modifiers
if (flags & CommonFlags.PUBLIC) {
this.error(
DiagnosticCode._0_modifier_cannot_be_used_here,
tn.range(accessStart, accessEnd), "public"
); // recoverable
} else if (flags & CommonFlags.PROTECTED) {
this.error(
DiagnosticCode._0_modifier_cannot_be_used_here,
tn.range(accessStart, accessEnd), "protected"
); // recoverable
} else if (flags & CommonFlags.PRIVATE) {
this.error(
DiagnosticCode._0_modifier_cannot_be_used_here,
tn.range(accessStart, accessEnd), "protected"
); // recoverable
}
if (flags & CommonFlags.STATIC) {
this.error(
DiagnosticCode._0_modifier_cannot_be_used_here,
tn.range(staticStart, staticEnd), "static"
); // recoverable
}
if (flags & CommonFlags.ABSTRACT) {
this.error(
DiagnosticCode._0_modifier_cannot_be_used_here,
tn.range(abstractStart, abstractEnd), "abstract"
); // recoverable
}
if (flags & CommonFlags.READONLY) {
this.error(
DiagnosticCode._0_modifier_cannot_be_used_here,
tn.range(readonlyStart, readonlyEnd), "readonly"
); // recoverable
}
let retIndex = this.parseIndexSignatureDeclaration(tn, decorators);
if (!retIndex) return null;
tn.skip(Token.SEMICOLON);
return retIndex;
}
if (!tn.skipIdentifier()) {
this.error(
DiagnosticCode.Identifier_expected,
tn.range()
);
return null;
}
name = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
}
var name = isConstructor
? Node.createConstructorExpression(tn.range())
: Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
var typeParameters: TypeParameterNode[] | null = null;
if (tn.skip(Token.LESSTHAN)) {
let typeParametersStart = tn.tokenPos;
@ -1979,6 +2055,69 @@ export class Parser extends DiagnosticEmitter {
return null;
}
parseIndexSignatureDeclaration(tn: Tokenizer, decorators: DecoratorNode[]): IndexSignatureDeclaration | null {
// at: '[': 'key' ':' Type ']' ':' Type
if (decorators.length) {
this.error(
DiagnosticCode.Decorators_are_not_valid_here,
Range.join(decorators[0].range, decorators[decorators.length - 1].range)
); // recoverable
}
var start = tn.tokenPos;
if (tn.skipIdentifier()) {
let id = tn.readIdentifier();
if (id == "key") {
if (tn.skip(Token.COLON)) {
let keyType = this.parseType(tn);
if (!keyType) return null;
if (keyType.kind != NodeKind.TYPE) {
this.error(
DiagnosticCode.Type_expected,
tn.range()
);
return null;
}
if (tn.skip(Token.CLOSEBRACKET)) {
if (tn.skip(Token.COLON)) {
let valueType = this.parseType(tn);
if (!valueType) return null;
return Node.createIndexSignatureDeclaration(<TypeNode>keyType, valueType, tn.range(start, tn.pos));
} else {
this.error(
DiagnosticCode._0_expected,
tn.range(), ":"
);
}
} else {
this.error(
DiagnosticCode._0_expected,
tn.range(), "]"
);
}
} else {
this.error(
DiagnosticCode._0_expected,
tn.range(), ":"
);
}
} else {
this.error(
DiagnosticCode._0_expected,
tn.range(), "key"
);
}
} else {
this.error(
DiagnosticCode.Identifier_expected,
tn.range()
);
}
return null;
}
parseNamespace(
tn: Tokenizer,
flags: CommonFlags,

View File

@ -965,6 +965,7 @@ export class Program extends DiagnosticEmitter {
}
break;
}
case NodeKind.INDEXSIGNATUREDECLARATION: break; // ignored for now
default: {
assert(false); // should have been reported while parsing
return;
@ -2413,6 +2414,21 @@ export class FunctionPrototype extends Element {
this.decoratorFlags = decoratorFlags;
}
/** Applies class type arguments to the context of a partially resolved instance method. */
applyClassTypeArguments(contextualTypeArguments: Map<string,Type>): void {
var classTypeArguments = assert(this.classTypeArguments); // set only if partial
var classDeclaration = assert(this.classPrototype).declaration;
var classTypeParameters = classDeclaration.typeParameters;
var numClassTypeParameters = classTypeParameters.length;
assert(numClassTypeParameters == classTypeArguments.length);
for (let i = 0; i < numClassTypeParameters; ++i) {
contextualTypeArguments.set(
classTypeParameters[i].name.text,
classTypeArguments[i]
);
}
}
toString(): string { return this.simpleName; }
}

View File

@ -51,7 +51,8 @@ import {
import {
Type,
Signature,
typesToString
typesToString,
TypeKind
} from "./types";
import {
@ -60,6 +61,10 @@ import {
CommonFlags
} from "./common";
import {
makeMap
} from "./util";
/** Indicates whether errors are reported or not. */
export enum ReportMode {
/** Report errors. */
@ -78,6 +83,8 @@ 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) {
@ -131,7 +138,7 @@ export class Resolver extends DiagnosticEmitter {
let instance = this.resolveClassInclTypeArguments(
<ClassPrototype>element,
typeNode.typeArguments,
contextualTypeArguments,
makeMap<string,Type>(contextualTypeArguments),
node
); // reports
if (!instance) return null;
@ -148,30 +155,29 @@ export class Resolver extends DiagnosticEmitter {
}
// resolve parameters
{
let typeArgumentNodes = typeNode.typeArguments;
if (typeArgumentNodes) {
let numTypeArguments = typeArgumentNodes.length;
let paramTypes = new Array<Type>(numTypeArguments);
for (let i = 0; i < numTypeArguments; ++i) {
let paramType = this.resolveType( // reports
typeArgumentNodes[i],
contextualTypeArguments,
reportMode
);
if (!paramType) return null;
paramTypes[i] = paramType;
}
if (numTypeArguments) { // can't be a placeholder if it has parameters
let instanceKey = typesToString(paramTypes);
if (instanceKey.length) {
localName += "<" + instanceKey + ">";
globalName += "<" + instanceKey + ">";
}
} else if (contextualTypeArguments) {
let placeholderType = contextualTypeArguments.get(globalName);
if (placeholderType) return placeholderType;
var typeArgumentNodes = typeNode.typeArguments;
var typeArguments: Type[] | null = null;
if (typeArgumentNodes) {
let numTypeArguments = typeArgumentNodes.length;
typeArguments = new Array<Type>(numTypeArguments);
for (let i = 0; i < numTypeArguments; ++i) {
let paramType = this.resolveType( // reports
typeArgumentNodes[i],
contextualTypeArguments,
reportMode
);
if (!paramType) return null;
typeArguments[i] = paramType;
}
if (numTypeArguments) { // can't be a placeholder if it has parameters
let instanceKey = typesToString(typeArguments);
if (instanceKey.length) {
localName += "<" + instanceKey + ">";
globalName += "<" + instanceKey + ">";
}
} else if (contextualTypeArguments) {
let placeholderType = contextualTypeArguments.get(globalName);
if (placeholderType) return placeholderType;
}
}
@ -187,6 +193,36 @@ export class Resolver extends DiagnosticEmitter {
}
}
// check built-in macro types
if (simpleName == "NATIVE") {
if (!(typeArguments && typeArguments.length == 1)) {
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
typeNode.range, "1", (typeArgumentNodes ? typeArgumentNodes.length : 1).toString(10)
);
}
return null;
}
switch (typeArguments[0].kind) {
case TypeKind.I8:
case TypeKind.I16:
case TypeKind.I32: return Type.i32;
case TypeKind.ISIZE: if (!this.program.options.isWasm64) return Type.i32;
case TypeKind.I64: return Type.i64;
case TypeKind.U8:
case TypeKind.U16:
case TypeKind.U32:
case TypeKind.BOOL: return Type.u32;
case TypeKind.USIZE: if (!this.program.options.isWasm64) return Type.u32;
case TypeKind.U64: return Type.u64;
case TypeKind.F32: return Type.f32;
case TypeKind.F64: return Type.f64;
case TypeKind.VOID: return Type.void;
default: assert(false);
}
}
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@ -255,39 +291,47 @@ export class Resolver extends DiagnosticEmitter {
resolveTypeArguments(
typeParameters: TypeParameterNode[],
typeArgumentNodes: CommonTypeNode[] | null,
contextualTypeArguments: Map<string,Type> | null = null,
contextualTypeArguments: Map<string,Type>,
alternativeReportNode: Node | null = null,
reportMode: ReportMode = ReportMode.REPORT
): Type[] | null {
var parameterCount = typeParameters.length;
var minParameterCount = 0;
var maxParameterCount = 0;
for (let i = 0; i < typeParameters.length; ++i) {
if (!typeParameters[i].defaultType) ++minParameterCount;
++maxParameterCount;
}
var argumentCount = typeArgumentNodes ? typeArgumentNodes.length : 0;
if (parameterCount != argumentCount) {
if (argumentCount) {
this.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
Range.join(
(<TypeNode[]>typeArgumentNodes)[0].range,
(<TypeNode[]>typeArgumentNodes)[argumentCount - 1].range
),
parameterCount.toString(10), argumentCount.toString(10)
);
} else if (alternativeReportNode) {
this.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
alternativeReportNode.range.atEnd, parameterCount.toString(10), "0"
);
}
if (argumentCount < minParameterCount || argumentCount > maxParameterCount) {
this.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
argumentCount
? Range.join(
(<TypeNode[]>typeArgumentNodes)[0].range,
(<TypeNode[]>typeArgumentNodes)[argumentCount - 1].range
)
: assert(alternativeReportNode).range.atEnd,
(argumentCount < minParameterCount ? minParameterCount : maxParameterCount).toString(10),
argumentCount.toString(10)
);
return null;
}
var typeArguments = new Array<Type>(parameterCount);
for (let i = 0; i < parameterCount; ++i) {
let type = this.resolveType( // reports
(<TypeNode[]>typeArgumentNodes)[i],
contextualTypeArguments,
reportMode
);
var typeArguments = new Array<Type>(maxParameterCount);
for (let i = 0; i < maxParameterCount; ++i) {
let type = i < argumentCount
? this.resolveType( // reports
(<TypeNode[]>typeArgumentNodes)[i],
contextualTypeArguments,
reportMode
)
: this.resolveType( // reports
assert(typeParameters[i].defaultType),
contextualTypeArguments,
reportMode
);
if (!type) return null;
// TODO: check extendsType
contextualTypeArguments.set(typeParameters[i].name.text, type);
typeArguments[i] = type;
}
return typeArguments;
@ -407,7 +451,7 @@ export class Resolver extends DiagnosticEmitter {
let getter = this.resolveFunction(
assert((<Property>target).getterPrototype),
null,
null,
makeMap<string,Type>(),
reportMode
);
if (!getter) return null;
@ -662,7 +706,7 @@ export class Resolver extends DiagnosticEmitter {
let instance = this.resolveFunctionInclTypeArguments(
<FunctionPrototype>target,
(<CallExpression>expression).typeArguments,
contextualFunction.flow.contextualTypeArguments,
makeMap<string,Type>(contextualFunction.flow.contextualTypeArguments),
expression,
reportMode
);
@ -710,10 +754,10 @@ export class Resolver extends DiagnosticEmitter {
resolveFunction(
prototype: FunctionPrototype,
typeArguments: Type[] | null,
contextualTypeArguments: Map<string,Type> | null = null,
contextualTypeArguments: Map<string,Type> = makeMap<string,Type>(),
reportMode: ReportMode = ReportMode.REPORT
): Function | null {
var classTypeArguments = prototype.classTypeArguments;
var classTypeArguments = prototype.classTypeArguments; // set only if partially resolved
var classInstanceKey = classTypeArguments ? typesToString(classTypeArguments) : "";
var instanceKey = typeArguments ? typesToString(typeArguments) : "";
var classInstances = prototype.instances.get(classInstanceKey);
@ -726,34 +770,8 @@ export class Resolver extends DiagnosticEmitter {
var isInstance = prototype.is(CommonFlags.INSTANCE);
var classPrototype = prototype.classPrototype;
// inherit contextual type arguments as provided. might be overridden.
var inheritedTypeArguments = contextualTypeArguments;
contextualTypeArguments = new Map();
if (inheritedTypeArguments) {
for (let [inheritedName, inheritedType] of inheritedTypeArguments) {
contextualTypeArguments.set(
inheritedName,
inheritedType
);
}
}
// override with class type arguments if a partially resolved instance method
if (classTypeArguments) { // set only if partially resolved
assert(prototype.is(CommonFlags.INSTANCE));
let classDeclaration = assert(classPrototype).declaration;
let classTypeParameters = classDeclaration.typeParameters;
let numClassTypeParameters = classTypeParameters.length;
assert(numClassTypeParameters == classTypeArguments.length);
for (let i = 0; i < numClassTypeParameters; ++i) {
contextualTypeArguments.set(
classTypeParameters[i].name.text,
classTypeArguments[i]
);
}
} else {
assert(!classTypeArguments);
}
// apply class type arguments if a partially resolved instance method
if (classTypeArguments) prototype.applyClassTypeArguments(contextualTypeArguments);
// override with function specific type arguments
var signatureNode = declaration.signature;
@ -869,13 +887,21 @@ export class Resolver extends DiagnosticEmitter {
resolveFunctionInclTypeArguments(
prototype: FunctionPrototype,
typeArgumentNodes: CommonTypeNode[] | null,
contextualTypeArguments: Map<string,Type> | null,
contextualTypeArguments: Map<string,Type>,
reportNode: Node,
reportMode: ReportMode = ReportMode.REPORT
): Function | null {
var resolvedTypeArguments: Type[] | null = null;
// Resolve type arguments if generic
if (prototype.is(CommonFlags.GENERIC)) {
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0);
// apply class type arguments if a partially resolved instance method
// FIXME: this is done once more in resolveFunction. required here for resolveTypeArguments,
// required there for just resolving a function no matter if a partial or not.
let classTypeArguments = prototype.classTypeArguments;
if (classTypeArguments) prototype.applyClassTypeArguments(contextualTypeArguments);
resolvedTypeArguments = this.resolveTypeArguments( // reports
assert(prototype.declaration.typeParameters),
typeArgumentNodes,
@ -884,7 +910,21 @@ export class Resolver extends DiagnosticEmitter {
reportMode
);
if (!resolvedTypeArguments) return null;
// Otherwise make sure that no type arguments have been specified
} else {
if (typeArgumentNodes !== null && typeArgumentNodes.length) {
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Type_0_is_not_generic,
reportNode.range, prototype.internalName
);
}
return null;
}
}
// Continue with concrete types
return this.resolveFunction(
prototype,
resolvedTypeArguments,
@ -897,7 +937,7 @@ export class Resolver extends DiagnosticEmitter {
resolveClass(
prototype: ClassPrototype,
typeArguments: Type[] | null,
contextualTypeArguments: Map<string,Type> | null = null,
contextualTypeArguments: Map<string,Type> = makeMap<string,Type>(),
reportMode: ReportMode = ReportMode.REPORT
): Class | null {
var instanceKey = typeArguments ? typesToString(typeArguments) : "";
@ -906,15 +946,6 @@ export class Resolver extends DiagnosticEmitter {
var instance = prototype.instances.get(instanceKey);
if (instance) return instance;
// Copy contextual type arguments so we don't pollute the original map
var inheritedTypeArguments = contextualTypeArguments;
contextualTypeArguments = new Map();
if (inheritedTypeArguments) {
for (let [inheritedName, inheritedType] of inheritedTypeArguments) {
contextualTypeArguments.set(inheritedName, inheritedType);
}
}
// Insert contextual type arguments for this operation. Internally, this method is always
// called with matching type parameter / argument counts.
var declaration = prototype.declaration;
@ -993,14 +1024,20 @@ export class Resolver extends DiagnosticEmitter {
}
// Resolve constructor by first applying the class type arguments
if (prototype.constructorPrototype) {
var constructorPrototype = prototype.constructorPrototype;
if (constructorPrototype) {
let constructorPartial = this.resolveFunctionPartially(
prototype.constructorPrototype,
constructorPrototype,
typeArguments,
reportMode
);
if (!constructorPartial) return null;
instance.constructorInstance = this.resolveFunction(constructorPartial, null, null, reportMode);
instance.constructorInstance = this.resolveFunction(
constructorPartial,
null,
makeMap<string,Type>(),
reportMode
);
}
// Resolve instance members
@ -1125,9 +1162,19 @@ export class Resolver extends DiagnosticEmitter {
reportMode
);
if (!operatorPartial) continue;
operatorInstance = this.resolveFunction(operatorPartial, null, null, reportMode);
operatorInstance = this.resolveFunction(
operatorPartial,
null,
makeMap<string,Type>(),
reportMode
);
} else {
operatorInstance = this.resolveFunction(overloadPrototype, null, null, reportMode);
operatorInstance = this.resolveFunction(
overloadPrototype,
null,
makeMap<string,Type>(),
reportMode
);
}
if (!operatorInstance) continue;
let overloads = instance.overloads;
@ -1141,7 +1188,7 @@ export class Resolver extends DiagnosticEmitter {
resolveClassInclTypeArguments(
prototype: ClassPrototype,
typeArgumentNodes: CommonTypeNode[] | null,
contextualTypeArguments: Map<string,Type> | null,
contextualTypeArguments: Map<string,Type>,
reportNode: Node,
reportMode: ReportMode = ReportMode.REPORT
): Class | null {
@ -1149,21 +1196,8 @@ export class Resolver extends DiagnosticEmitter {
// Resolve type arguments if generic
if (prototype.is(CommonFlags.GENERIC)) {
let typeParameterNodes = prototype.declaration.typeParameters;
let expectedTypeArguments = typeParameterNodes.length;
assert(expectedTypeArguments > 0);
let actualTypeArguments = typeArgumentNodes !== null ? typeArgumentNodes.length : 0;
if (expectedTypeArguments != actualTypeArguments) {
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Expected_0_type_arguments_but_got_1,
reportNode.range, expectedTypeArguments.toString(10), actualTypeArguments.toString(10)
);
}
return null;
}
resolvedTypeArguments = this.resolveTypeArguments(
typeParameterNodes,
assert(prototype.declaration.typeParameters),
typeArgumentNodes,
contextualTypeArguments,
reportNode,

26
src/util/collections.ts Normal file
View File

@ -0,0 +1,26 @@
export function makeArray<V>(original: Array<V> | null = null): Array<V> {
if (original) {
let cloned = new Array<V>(original.length);
for (let i = 0, k = original.length; i < k; ++i) unchecked(cloned[i] = original[i]);
return cloned;
}
return new Array<V>();
}
export function makeSet<V>(original: Set<V> | null = null): Set<V> {
if (original) {
let cloned = new Set<V>();
for (let v of original) cloned.add(v);
return cloned;
}
return new Set<V>();
}
export function makeMap<K,V>(original: Map<K,V> | null = null): Map<K,V> {
if (original) {
let cloned = new Map<K,V>();
for (let [k, v] of original) cloned.set(k, v);
return cloned;
}
return new Map<K,V>();
}

View File

@ -5,6 +5,7 @@
*//***/
export * from "./charcode";
export * from "./collections";
export * from "./path";
export * from "./text";
export * from "./binary";

View File

@ -3,8 +3,8 @@ import {
HEADER_SIZE,
allocateUnsafe,
reallocateUnsafe,
loadUnsafe,
storeUnsafe
LOAD,
STORE
} from "./internal/arraybuffer";
import {
@ -32,6 +32,7 @@ import {
} from "./builtins";
export class Array<T> {
[key: number]: T; // compatibility only
/* @internal */ buffer_: ArrayBuffer;
/* @internal */ length_: i32;
@ -74,7 +75,7 @@ export class Array<T> {
every(callbackfn: (element: T, index: i32, array: Array<T>) => bool): bool {
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
if (!callbackfn(loadUnsafe<T,T>(buffer, index), index, this)) return false;
if (!callbackfn(LOAD<T>(buffer, index), index, this)) return false;
}
return true;
}
@ -82,7 +83,7 @@ export class Array<T> {
findIndex(predicate: (element: T, index: i32, array: Array<T>) => bool): i32 {
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
if (predicate(loadUnsafe<T,T>(buffer, index), index, this)) return index;
if (predicate(LOAD<T>(buffer, index), index, this)) return index;
}
return -1;
}
@ -91,13 +92,13 @@ export class Array<T> {
private __get(index: i32): T {
var buffer = this.buffer_;
return <u32>index < <u32>(buffer.byteLength >>> alignof<T>())
? loadUnsafe<T,T>(buffer, index)
? LOAD<T>(buffer, index)
: <T>unreachable();
}
@operator("{}")
private __unchecked_get(index: i32): T {
return loadUnsafe<T,T>(this.buffer_, index);
return LOAD<T>(this.buffer_, index);
}
@operator("[]=")
@ -111,13 +112,13 @@ export class Array<T> {
this.buffer_ = buffer;
this.length_ = index + 1;
}
storeUnsafe<T,T>(buffer, index, value);
STORE<T>(buffer, index, value);
if (isManaged<T>()) __gc_link(changetype<usize>(this), changetype<usize>(value)); // tslint:disable-line
}
@operator("{}=")
private __unchecked_set(index: i32, value: T): void {
storeUnsafe<T,T>(this.buffer_, index, value);
STORE<T>(this.buffer_, index, value);
if (isManaged<T>()) __gc_link(changetype<usize>(this), changetype<usize>(value)); // tslint:disable-line
}
@ -138,7 +139,7 @@ export class Array<T> {
}
} else {
for (; start < end; ++start) {
storeUnsafe<T,T>(buffer, start, value);
STORE<T>(buffer, start, value);
}
}
return this;
@ -155,7 +156,7 @@ export class Array<T> {
if (fromIndex < 0) fromIndex = max(length + fromIndex, 0);
var buffer = this.buffer_;
while (fromIndex < length) {
if (loadUnsafe<T,T>(buffer, fromIndex) == searchElement) return fromIndex;
if (LOAD<T>(buffer, fromIndex) == searchElement) return fromIndex;
++fromIndex;
}
return -1;
@ -168,7 +169,7 @@ export class Array<T> {
else if (fromIndex >= length) fromIndex = length - 1;
var buffer = this.buffer_;
while (fromIndex >= 0) { // ^
if (loadUnsafe<T,T>(buffer, fromIndex) == searchElement) return fromIndex;
if (LOAD<T>(buffer, fromIndex) == searchElement) return fromIndex;
--fromIndex;
}
return -1;
@ -186,7 +187,7 @@ export class Array<T> {
this.buffer_ = buffer;
}
this.length_ = newLength;
storeUnsafe<T,T>(buffer, length, element);
STORE<T>(buffer, length, element);
if (isManaged<T>()) __gc_link(changetype<usize>(this), changetype<usize>(element)); // tslint:disable-line
return newLength;
}
@ -228,7 +229,7 @@ export class Array<T> {
from += count - 1;
to += count - 1;
while (count) {
storeUnsafe<T,T>(buffer, to, loadUnsafe<T,T>(buffer, from));
STORE<T>(buffer, to, LOAD<T>(buffer, from));
--from, --to, --count;
}
} else {
@ -244,7 +245,7 @@ export class Array<T> {
pop(): T {
var length = this.length_;
if (length < 1) throw new RangeError("Array is empty");
var element = loadUnsafe<T,T>(this.buffer_, --length);
var element = LOAD<T>(this.buffer_, --length);
this.length_ = length;
return element;
}
@ -252,7 +253,7 @@ export class Array<T> {
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void {
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
callbackfn(loadUnsafe<T,T>(buffer, index), index, this);
callbackfn(LOAD<T>(buffer, index), index, this);
}
}
@ -262,7 +263,7 @@ export class Array<T> {
var result = new Array<U>(length);
var resultBuffer = result.buffer_;
for (let index = 0; index < length && index < this.length_; ++index) {
storeUnsafe<U,U>(resultBuffer, index, callbackfn(loadUnsafe<T,T>(buffer, index), index, this));
STORE<U>(resultBuffer, index, callbackfn(LOAD<T>(buffer, index), index, this));
}
return result;
}
@ -272,7 +273,7 @@ export class Array<T> {
var length = this.length_;
var result = new Array<T>();
for (let index = 0; index < length && index < this.length_; ++index) {
let value = loadUnsafe<T,T>(buffer, index);
let value = LOAD<T>(buffer, index);
if (callbackfn(value, index, this)) result.push(value);
}
return result;
@ -285,7 +286,7 @@ export class Array<T> {
var accum = initialValue;
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
accum = callbackfn(accum, loadUnsafe<T,T>(buffer, index), index, this);
accum = callbackfn(accum, LOAD<T>(buffer, index), index, this);
}
return accum;
}
@ -297,7 +298,7 @@ export class Array<T> {
var accum = initialValue;
var buffer = this.buffer_;
for (let index: i32 = this.length_ - 1; index >= 0; --index) {
accum = callbackfn(accum, loadUnsafe<T,T>(buffer, index), index, this);
accum = callbackfn(accum, LOAD<T>(buffer, index), index, this);
}
return accum;
}
@ -306,14 +307,14 @@ export class Array<T> {
var length = this.length_;
if (length < 1) throw new RangeError("Array is empty");
var buffer = this.buffer_;
var element = loadUnsafe<T,T>(buffer, 0);
var element = LOAD<T>(buffer, 0);
var lastIndex = length - 1;
memory.copy(
changetype<usize>(buffer) + HEADER_SIZE,
changetype<usize>(buffer) + HEADER_SIZE + sizeof<T>(),
<usize>lastIndex << alignof<T>()
);
storeUnsafe<T,T>(buffer, lastIndex, <T>null);
STORE<T>(buffer, lastIndex, <T>null);
this.length_ = lastIndex;
return element;
}
@ -321,7 +322,7 @@ export class Array<T> {
some(callbackfn: (element: T, index: i32, array: Array<T>) => bool): bool {
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
if (callbackfn(loadUnsafe<T,T>(buffer, index), index, this)) return true;
if (callbackfn(LOAD<T>(buffer, index), index, this)) return true;
}
return false;
}
@ -343,7 +344,7 @@ export class Array<T> {
changetype<usize>(buffer) + HEADER_SIZE,
<usize>(capacity - 1) << alignof<T>()
);
storeUnsafe<T,T>(buffer, 0, element);
STORE<T>(buffer, 0, element);
this.length_ = newLength;
if (isManaged<T>()) __gc_link(changetype<usize>(this), changetype<usize>(element)); // tslint:disable-line
return newLength;
@ -396,9 +397,9 @@ export class Array<T> {
reverse(): Array<T> {
var buffer = this.buffer_;
for (let front = 0, back = this.length_ - 1; front < back; ++front, --back) {
let temp = loadUnsafe<T,T>(buffer, front);
storeUnsafe<T,T>(buffer, front, loadUnsafe<T,T>(buffer, back));
storeUnsafe<T,T>(buffer, back, temp);
let temp = LOAD<T>(buffer, front);
STORE<T>(buffer, front, LOAD<T>(buffer, back));
STORE<T>(buffer, back, temp);
}
return this;
}
@ -411,11 +412,11 @@ export class Array<T> {
if (length <= 1) return this;
var buffer = this.buffer_;
if (length == 2) {
let a = loadUnsafe<T,T>(buffer, 1); // a = arr[1]
let b = loadUnsafe<T,T>(buffer, 0); // b = arr[0]
let a = LOAD<T>(buffer, 1); // a = arr[1]
let b = LOAD<T>(buffer, 0); // b = arr[0]
if (comparator(a, b) < 0) {
storeUnsafe<T,T>(buffer, 1, b); // arr[1] = b;
storeUnsafe<T,T>(buffer, 0, a); // arr[0] = a;
STORE<T>(buffer, 1, b); // arr[1] = b;
STORE<T>(buffer, 0, a); // arr[0] = a;
}
return this;
}
@ -444,14 +445,14 @@ export class Array<T> {
var hasSeparator = sepLen != 0;
if (value instanceof bool) {
if (!lastIndex) {
return select<string>("true", "false", loadUnsafe<T,bool>(buffer, 0));
return select<string>("true", "false", LOAD<T,bool>(buffer, 0));
}
let valueLen = 5; // max possible length of element len("false")
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
let result = allocateUnsafeString(estLen);
let offset = 0;
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,bool>(buffer, i);
value = LOAD<T,bool>(buffer, i);
valueLen = 4 + <i32>(!value);
copyUnsafeString(result, offset, select<string>("true", "false", value), 0, valueLen);
offset += valueLen;
@ -460,7 +461,7 @@ export class Array<T> {
offset += sepLen;
}
}
value = loadUnsafe<T,bool>(buffer, lastIndex);
value = LOAD<T,bool>(buffer, lastIndex);
valueLen = 4 + <i32>(!value);
copyUnsafeString(result, offset, select<string>("true", "false", value), 0, valueLen);
offset += valueLen;
@ -473,21 +474,21 @@ export class Array<T> {
return out;
} else if (isInteger<T>()) {
if (!lastIndex) {
return changetype<string>(itoa<T>(loadUnsafe<T,T>(buffer, 0)));
return changetype<string>(itoa<T>(LOAD<T>(buffer, 0)));
}
const valueLen = (sizeof<T>() <= 4 ? 10 : 20) + <i32>isSigned<T>();
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
let result = allocateUnsafeString(estLen);
let offset = 0;
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,T>(buffer, i);
value = LOAD<T>(buffer, i);
offset += itoa_stream<T>(changetype<usize>(result), offset, value);
if (hasSeparator) {
copyUnsafeString(result, offset, separator, 0, sepLen);
offset += sepLen;
}
}
value = loadUnsafe<T,T>(buffer, lastIndex);
value = LOAD<T>(buffer, lastIndex);
offset += itoa_stream<T>(changetype<usize>(result), offset, value);
let out = result;
if (estLen > offset) {
@ -497,21 +498,21 @@ export class Array<T> {
return out;
} else if (isFloat<T>()) {
if (!lastIndex) {
return changetype<string>(dtoa(loadUnsafe<T,f64>(buffer, 0)));
return changetype<string>(dtoa(LOAD<T,f64>(buffer, 0)));
}
const valueLen = MAX_DOUBLE_LENGTH;
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
let result = allocateUnsafeString(estLen);
let offset = 0;
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,f64>(buffer, i);
value = LOAD<T,f64>(buffer, i);
offset += dtoa_stream(changetype<usize>(result), offset, value);
if (hasSeparator) {
copyUnsafeString(result, offset, separator, 0, sepLen);
offset += sepLen;
}
}
value = loadUnsafe<T,f64>(buffer, lastIndex);
value = LOAD<T,f64>(buffer, lastIndex);
offset += dtoa_stream(changetype<usize>(result), offset, value);
let out = result;
if (estLen > offset) {
@ -521,16 +522,16 @@ export class Array<T> {
return out;
} else if (isString<T>()) {
if (!lastIndex) {
return loadUnsafe<T,string>(buffer, 0);
return LOAD<string>(buffer, 0);
}
let estLen = 0;
for (let i = 0, len = lastIndex + 1; i < len; ++i) {
estLen += loadUnsafe<T,string>(buffer, i).length;
estLen += LOAD<string>(buffer, i).length;
}
let offset = 0;
let result = allocateUnsafeString(estLen + sepLen * lastIndex);
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,String>(buffer, i);
value = LOAD<string>(buffer, i);
if (value) {
let valueLen = value.length; // tslint:disable-line:no-unsafe-any
copyUnsafeString(result, offset, value, 0, valueLen); // tslint:disable-line:no-unsafe-any
@ -541,7 +542,7 @@ export class Array<T> {
offset += sepLen;
}
}
value = loadUnsafe<T,String>(buffer, lastIndex);
value = LOAD<string>(buffer, lastIndex);
if (value) {
let valueLen = value.length; // tslint:disable-line:no-unsafe-any
copyUnsafeString(result, offset, value, 0, valueLen); // tslint:disable-line:no-unsafe-any
@ -549,15 +550,15 @@ export class Array<T> {
return result;
} else if (isArray<T>()) {
if (!lastIndex) {
value = loadUnsafe<T,T>(buffer, 0);
value = LOAD<T>(buffer, 0);
return value ? value.join(separator) : ""; // tslint:disable-line:no-unsafe-any
}
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,T>(buffer, i);
value = LOAD<T>(buffer, i);
if (value) result += value.join(separator); // tslint:disable-line:no-unsafe-any
if (hasSeparator) result += separator;
}
value = loadUnsafe<T,T>(buffer, lastIndex);
value = LOAD<T>(buffer, lastIndex);
if (value) result += value.join(separator); // tslint:disable-line:no-unsafe-any
return result;
} else if (isReference<T>()) { // References
@ -567,7 +568,7 @@ export class Array<T> {
let result = allocateUnsafeString(estLen);
let offset = 0;
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,T>(buffer, i);
value = LOAD<T>(buffer, i);
if (value) {
copyUnsafeString(result, offset, changetype<String>("[object Object]"), 0, valueLen);
offset += valueLen;
@ -577,7 +578,7 @@ export class Array<T> {
offset += sepLen;
}
}
if (loadUnsafe<T,T>(buffer, lastIndex)) {
if (LOAD<T>(buffer, lastIndex)) {
copyUnsafeString(result, offset, changetype<String>("[object Object]"), 0, valueLen);
offset += valueLen;
}

View File

@ -365,6 +365,8 @@ declare namespace 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> = T;
// User-defined diagnostic macros

View File

@ -1,6 +1,6 @@
import {
loadUnsafeWithOffset,
storeUnsafeWithOffset
LOAD,
STORE
} from "./arraybuffer";
import {
@ -52,15 +52,15 @@ export function insertionSort<T>(
comparator: (a: T, b: T) => i32
): void {
for (let i = 0; i < length; i++) {
let a = loadUnsafeWithOffset<T,T>(buffer, i, byteOffset); // a = arr[i]
let a = LOAD<T>(buffer, i, byteOffset); // a = arr[i]
let j = i - 1;
while (j >= 0) {
let b = loadUnsafeWithOffset<T,T>(buffer, j, byteOffset); // b = arr[j]
let b = LOAD<T>(buffer, j, byteOffset); // b = arr[j]
if (comparator(a, b) < 0) {
storeUnsafeWithOffset<T,T>(buffer, j-- + 1, b, byteOffset); // arr[j + 1] = b
STORE<T>(buffer, j-- + 1, b, byteOffset); // arr[j + 1] = b
} else break;
}
storeUnsafeWithOffset<T,T>(buffer, j + 1, a, byteOffset); // arr[j + 1] = a
STORE<T>(buffer, j + 1, a, byteOffset); // arr[j + 1] = a
}
}
@ -84,37 +84,37 @@ export function weakHeapSort<T>(
while ((j & 1) == (load<u32>(bitset + (j >> 6 << shift32)) >> (j >> 1 & 31) & 1)) j >>= 1;
let p = j >> 1;
let a = loadUnsafeWithOffset<T,T>(buffer, p, byteOffset); // a = arr[p]
let b = loadUnsafeWithOffset<T,T>(buffer, i, byteOffset); // b = arr[i]
let a = LOAD<T>(buffer, p, byteOffset); // a = arr[p]
let b = LOAD<T>(buffer, i, byteOffset); // b = arr[i]
if (comparator(a, b) < 0) {
store<u32>(
bitset + (i >> 5 << shift32),
load<u32>(bitset + (i >> 5 << shift32)) ^ (1 << (i & 31))
);
storeUnsafeWithOffset<T,T>(buffer, i, a, byteOffset); // arr[i] = a
storeUnsafeWithOffset<T,T>(buffer, p, b, byteOffset); // arr[p] = b
STORE<T>(buffer, i, a, byteOffset); // arr[i] = a
STORE<T>(buffer, p, b, byteOffset); // arr[p] = b
}
}
for (let i = length - 1; i >= 2; i--) {
let a = loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset);
storeUnsafeWithOffset<T,T>(buffer, 0, loadUnsafeWithOffset<T,T>(buffer, i, byteOffset), byteOffset);
storeUnsafeWithOffset<T,T>(buffer, i, a, byteOffset);
let a = LOAD<T>(buffer, 0, byteOffset);
STORE<T>(buffer, 0, LOAD<T>(buffer, i, byteOffset), byteOffset);
STORE<T>(buffer, i, a, byteOffset);
let x = 1, y: i32;
while ((y = (x << 1) + ((load<u32>(bitset + (x >> 5 << shift32)) >> (x & 31)) & 1)) < i) x = y;
while (x > 0) {
a = loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset); // a = arr[0]
let b = loadUnsafeWithOffset<T,T>(buffer, x, byteOffset); // b = arr[x]
a = LOAD<T>(buffer, 0, byteOffset); // a = arr[0]
let b = LOAD<T>(buffer, x, byteOffset); // b = arr[x]
if (comparator(a, b) < 0) {
store<u32>(
bitset + (x >> 5 << shift32),
load<u32>(bitset + (x >> 5 << shift32)) ^ (1 << (x & 31))
);
storeUnsafeWithOffset<T,T>(buffer, x, a, byteOffset); // arr[x] = a
storeUnsafeWithOffset<T,T>(buffer, 0, b, byteOffset); // arr[0] = b
STORE<T>(buffer, x, a, byteOffset); // arr[x] = a
STORE<T>(buffer, 0, b, byteOffset); // arr[0] = b
}
x >>= 1;
}
@ -122,7 +122,7 @@ export function weakHeapSort<T>(
memory.free(bitset);
var t = loadUnsafeWithOffset<T,T>(buffer, 1, byteOffset); // t = arr[1]
storeUnsafeWithOffset<T,T>(buffer, 1, loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset), byteOffset);
storeUnsafeWithOffset<T,T>(buffer, 0, t, byteOffset); // arr[0] = t
var t = LOAD<T>(buffer, 1, byteOffset); // t = arr[1]
STORE<T>(buffer, 1, LOAD<T>(buffer, 0, byteOffset), byteOffset);
STORE<T>(buffer, 0, t, byteOffset); // arr[0] = t
}

View File

@ -71,33 +71,13 @@ export function reallocateUnsafe(buffer: ArrayBuffer, newByteLength: i32): Array
// * `i32.load8` ^= `<i32>load<i8>(...)` that reads an i8 but returns an i32, or
// * `i64.load32_s` ^= `<i64>load<i32>(...)`) that reads a 32-bit as a 64-bit integer
//
// without having to emit an additional instruction for conversion purposes. This is useful for
// small integers only of course. When dealing with reference types like classes, both parameters
// are usually the same, even though it looks ugly.
//
// TODO: is there a better way to model this?
// without having to emit an additional instruction for conversion purposes. The second parameter
// can be omitted for references and other loads and stores that simply return the exact type.
@inline export function loadUnsafe<T,TOut>(buffer: ArrayBuffer, index: i32): TOut {
return <TOut>load<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()), HEADER_SIZE);
@inline export function LOAD<T,TOut = T>(buffer: ArrayBuffer, index: i32, byteOffset: i32 = 0): TOut {
return <TOut>load<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()) + <usize>byteOffset, HEADER_SIZE);
}
@inline export function storeUnsafe<T,TIn>(buffer: ArrayBuffer, index: i32, value: TIn): void {
store<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()), value, HEADER_SIZE);
}
@inline export function loadUnsafeWithOffset<T,TOut>(
buffer: ArrayBuffer,
index: i32,
byteOffset: i32
): TOut {
return <TOut>load<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), HEADER_SIZE);
}
@inline export function storeUnsafeWithOffset<T,TIn>(
buffer: ArrayBuffer,
index: i32,
value: TIn,
byteOffset: i32
): void {
store<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), value, HEADER_SIZE);
@inline export function STORE<T,TIn = T>(buffer: ArrayBuffer, index: i32, value: TIn, byteOffset: i32 = 0): void {
store<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()) + <usize>byteOffset, value, HEADER_SIZE);
}

View File

@ -7,7 +7,7 @@ import {
} from "./string";
import {
loadUnsafe
LOAD
} from "./arraybuffer";
export const MAX_DOUBLE_LENGTH = 28;
@ -124,7 +124,7 @@ export function decimalCount32(value: u32): u32 {
let t = l * 1233 >>> 12; // log10
let lutbuf = <ArrayBuffer>POWERS10().buffer_;
let power = loadUnsafe<u32,u32>(lutbuf, t);
let power = LOAD<u32>(lutbuf, t);
t -= <u32>(value < power);
return t + 1;
} else {
@ -154,7 +154,7 @@ export function decimalCount64(value: u64): u32 {
let t = l * 1233 >>> 12; // log10
let lutbuf = <ArrayBuffer>POWERS10().buffer_;
let power = loadUnsafe<u32,u64>(lutbuf, t - 10);
let power = LOAD<u32,u64>(lutbuf, t - 10);
t -= <u32>(value < 10000000000 * power);
return t + 1;
} else {
@ -188,8 +188,8 @@ function utoa32_lut(buffer: usize, num: u32, offset: usize): void {
let d1 = r / 100;
let d2 = r % 100;
let digits1 = loadUnsafe<u32,u64>(lutbuf, d1);
let digits2 = loadUnsafe<u32,u64>(lutbuf, d2);
let digits1 = LOAD<u32,u64>(lutbuf, d1);
let digits2 = LOAD<u32,u64>(lutbuf, d2);
offset -= 4;
store<u64>(buffer + (offset << 1), digits1 | (digits2 << 32), STRING_HEADER_SIZE);
@ -200,13 +200,13 @@ function utoa32_lut(buffer: usize, num: u32, offset: usize): void {
let d1 = num % 100;
num = t;
offset -= 2;
let digits = loadUnsafe<u32,u32>(lutbuf, d1);
let digits = LOAD<u32>(lutbuf, d1);
store<u32>(buffer + (offset << 1), digits, STRING_HEADER_SIZE);
}
if (num >= 10) {
offset -= 2;
let digits = loadUnsafe<u32,u32>(lutbuf, num);
let digits = LOAD<u32>(lutbuf, num);
store<u32>(buffer + (offset << 1), digits, STRING_HEADER_SIZE);
} else {
offset -= 1;
@ -231,14 +231,14 @@ function utoa64_lut(buffer: usize, num: u64, offset: usize): void {
let c1 = c / 100;
let c2 = c % 100;
let digits1 = loadUnsafe<u32,u64>(lutbuf, c1);
let digits2 = loadUnsafe<u32,u64>(lutbuf, c2);
let digits1 = LOAD<u32,u64>(lutbuf, c1);
let digits2 = LOAD<u32,u64>(lutbuf, c2);
offset -= 4;
store<u64>(buffer + (offset << 1), digits1 | (digits2 << 32), STRING_HEADER_SIZE);
digits1 = loadUnsafe<u32,u64>(lutbuf, b1);
digits2 = loadUnsafe<u32,u64>(lutbuf, b2);
digits1 = LOAD<u32,u64>(lutbuf, b1);
digits2 = LOAD<u32,u64>(lutbuf, b2);
offset -= 4;
store<u64>(buffer + (offset << 1), digits1 | (digits2 << 32), STRING_HEADER_SIZE);
@ -438,8 +438,8 @@ function getCachedPower(minExp: i32): void {
_K = 348 - (index << 3); // decimal exponent no need lookup table
var frcPowers = <ArrayBuffer>FRC_POWERS().buffer_;
var expPowers = <ArrayBuffer>EXP_POWERS().buffer_;
_frc_pow = loadUnsafe<u64,u64>(frcPowers, index);
_exp_pow = loadUnsafe<i16,i32>(expPowers, index);
_frc_pow = LOAD<u64>(frcPowers, index);
_exp_pow = LOAD<i16,i32>(expPowers, index);
}
@inline
@ -513,7 +513,7 @@ function genDigits(buffer: usize, w_frc: u64, w_exp: i32, mp_frc: u64, mp_exp: i
let tmp = ((<u64>p1) << one_exp) + p2;
if (tmp <= delta) {
_K += kappa;
grisuRound(buffer, len, delta, tmp, loadUnsafe<u32,u64>(powers10, kappa) << one_exp, wp_w_frc);
grisuRound(buffer, len, delta, tmp, LOAD<u32,u64>(powers10, kappa) << one_exp, wp_w_frc);
return len;
}
}
@ -529,7 +529,7 @@ function genDigits(buffer: usize, w_frc: u64, w_exp: i32, mp_frc: u64, mp_exp: i
--kappa;
if (p2 < delta) {
_K += kappa;
wp_w_frc *= loadUnsafe<u32,u64>(powers10, -kappa);
wp_w_frc *= LOAD<u32,u64>(powers10, -kappa);
grisuRound(buffer, len, delta, p2, one_frc, wp_w_frc);
return len;
}

View File

@ -2,21 +2,18 @@ import {
HEADER_SIZE as AB_HEADER_SIZE,
MAX_BLENGTH as AB_MAX_BLENGTH,
allocateUnsafe,
loadUnsafeWithOffset,
storeUnsafeWithOffset
LOAD,
STORE
} from "./arraybuffer";
import {
insertionSort,
weakHeapSort,
defaultComparator
weakHeapSort
} from "./array";
// The internal TypedArray class uses two type parameters for the same reason as `loadUnsafe` and
// `storeUnsafe` in 'internal/arraybuffer.ts'. See the documentation there for details.
/** Typed array base class. Not a global object. */
export abstract class TypedArray<T,TNative> {
export abstract class TypedArray<T> {
[key: number]: T; // compatibility only
readonly buffer: ArrayBuffer;
readonly byteOffset: i32;
@ -41,116 +38,142 @@ export abstract class TypedArray<T,TNative> {
@operator("[]")
protected __get(index: i32): T {
if (<u32>index >= <u32>(this.byteLength >>> alignof<T>())) throw new Error("Index out of bounds");
return loadUnsafeWithOffset<T,T>(this.buffer, index, this.byteOffset);
return LOAD<T>(this.buffer, index, this.byteOffset);
}
@inline @operator("{}")
protected __unchecked_get(index: i32): T {
return loadUnsafeWithOffset<T,T>(this.buffer, index, this.byteOffset);
return LOAD<T>(this.buffer, index, this.byteOffset);
}
@operator("[]=")
protected __set(index: i32, value: TNative): void {
protected __set(index: i32, value: NATIVE<T>): void {
if (<u32>index >= <u32>(this.byteLength >>> alignof<T>())) throw new Error("Index out of bounds");
storeUnsafeWithOffset<T,TNative>(this.buffer, index, value, this.byteOffset);
STORE<T,NATIVE<T>>(this.buffer, index, value, this.byteOffset);
}
@inline @operator("{}=")
protected __unchecked_set(index: i32, value: TNative): void {
storeUnsafeWithOffset<T,TNative>(this.buffer, index, value, this.byteOffset);
protected __unchecked_set(index: i32, value: NATIVE<T>): void {
STORE<T,NATIVE<T>>(this.buffer, index, value, this.byteOffset);
}
// copyWithin(target: i32, start: i32, end: i32 = this.length): this
}
fill(value: TNative, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
var buffer = this.buffer;
var byteOffset = this.byteOffset;
var len = this.length;
start = start < 0 ? max(len + start, 0) : min(start, len);
end = end < 0 ? max(len + end, 0) : min(end, len);
if (sizeof<T>() == 1) {
if (start < end) {
memory.fill(
changetype<usize>(buffer) + start + byteOffset + AB_HEADER_SIZE,
<u8>value,
<usize>(end - start)
);
}
} else {
for (; start < end; ++start) {
storeUnsafeWithOffset<T,TNative>(buffer, start, value, byteOffset);
}
}
return this;
}
@inline
subarray(begin: i32 = 0, end: i32 = i32.MAX_VALUE): TypedArray<T,TNative> {
var length = this.length;
if (begin < 0) begin = max(length + begin, 0);
else begin = min(begin, length);
if (end < 0) end = max(length + end, begin);
else end = max(min(end, length), begin);
var slice = memory.allocate(offsetof<this>());
store<usize>(slice, this.buffer, offsetof<this>("buffer"));
store<i32>(slice, this.byteOffset + (begin << alignof<T>()), offsetof<this>("byteOffset"));
store<i32>(slice, (end - begin) << alignof<T>(), offsetof<this>("byteLength"));
return changetype<this>(slice);
}
sort(comparator: (a: T, b: T) => i32 = defaultComparator<T>()): this {
var byteOffset = this.byteOffset;
var length = this.length;
if (length <= 1) return this;
var buffer = this.buffer;
if (length == 2) {
let a = loadUnsafeWithOffset<T,T>(buffer, 1, byteOffset);
let b = loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset);
if (comparator(a, b) < 0) {
storeUnsafeWithOffset<T,T>(buffer, 1, b, byteOffset);
storeUnsafeWithOffset<T,T>(buffer, 0, a, byteOffset);
}
return this;
}
if (isReference<T>()) {
// TODO replace this to faster stable sort (TimSort) when it implemented
insertionSort<T>(buffer, byteOffset, length, comparator);
return this;
} else {
if (length < 256) {
insertionSort<T>(buffer, byteOffset, length, comparator);
} else {
weakHeapSort<T>(buffer, byteOffset, length, comparator);
}
return this;
}
}
/**
* TypedArray reduce implementation. This is a method that will be called from the parent,
* passing types down from the child class using the typed parameters TypedArrayType and
* ReturnType respectively. This implementation requires an initial value, and the direction.
* When direction is true, reduce will reduce from the right side.
*/
@inline
protected reduce_internal<TypedArrayType, ReturnType>(
callbackfn: (accumulator: ReturnType, value: T, index: i32, array: TypedArrayType) => ReturnType,
array: TypedArrayType,
initialValue: ReturnType,
direction: bool = false,
): ReturnType {
var index: i32 = direction ? this.length - 1 : 0;
var length: i32 = direction ? -1 : this.length;
while (index != length) {
initialValue = callbackfn(
initialValue,
this.__unchecked_get(index),
index,
array,
@inline
export function FILL<TArray extends TypedArray<T>, T>(
array: TArray,
value: NATIVE<T>,
start: i32,
end: i32
): TArray {
var buffer = array.buffer;
var byteOffset = array.byteOffset;
var len = array.length;
start = start < 0 ? max(len + start, 0) : min(start, len);
end = end < 0 ? max(len + end, 0) : min(end, len);
if (sizeof<T>() == 1) {
if (start < end) {
memory.fill(
changetype<usize>(buffer) + start + byteOffset + AB_HEADER_SIZE,
<u8>value,
<usize>(end - start)
);
index = direction ? index - 1 : index + 1;
}
return initialValue;
} else {
for (; start < end; ++start) {
STORE<T,NATIVE<T>>(buffer, start, value, byteOffset);
}
}
return array;
}
@inline
export function SORT<TArray extends TypedArray<T>, T>(
array: TArray,
comparator: (a: T, b: T) => i32
): TArray {
var byteOffset = array.byteOffset;
var length = array.length;
if (length <= 1) return array;
var buffer = array.buffer;
if (length == 2) {
let a = LOAD<T>(buffer, 1, byteOffset);
let b = LOAD<T>(buffer, 0, byteOffset);
if (comparator(a, b) < 0) {
STORE<T>(buffer, 1, b, byteOffset);
STORE<T>(buffer, 0, a, byteOffset);
}
return array;
}
if (isReference<T>()) {
// TODO replace this to faster stable sort (TimSort) when it implemented
insertionSort<T>(buffer, byteOffset, length, comparator);
return array;
} else {
if (length < 256) {
insertionSort<T>(buffer, byteOffset, length, comparator);
} else {
weakHeapSort<T>(buffer, byteOffset, length, comparator);
}
return array;
}
}
@inline
export function SUBARRAY<TArray extends TypedArray<T>, T>(
array: TArray,
begin: i32,
end: i32
): TArray {
var length = <i32>array.length;
if (begin < 0) begin = max(length + begin, 0);
else begin = min(begin, length);
if (end < 0) end = max(length + end, begin);
else end = max(min(end, length), begin);
var slice = memory.allocate(offsetof<TArray>());
store<usize>(slice, array.buffer, offsetof<TArray>("buffer"));
store<i32>(slice, <i32>array.byteOffset + (begin << alignof<T>()), offsetof<TArray>("byteOffset"));
store<i32>(slice, (end - begin) << alignof<T>(), offsetof<TArray>("byteLength"));
return changetype<TArray>(slice);
}
@inline
export function REDUCE<TArray extends TypedArray<T>, T, TRet>(
array: TArray,
callbackfn: (accumulator: TRet, value: T, index: i32, array: TArray) => TRet,
initialValue: TRet
): TRet {
var index = 0;
var length = <i32>array.length;
while (index != length) {
initialValue = callbackfn(
initialValue,
unchecked(array[index]),
index,
array,
);
++index;
}
return initialValue;
}
@inline
export function REDUCE_RIGHT<TArray extends TypedArray<T>, T, TRet>(
array: TArray,
callbackfn: (accumulator: TRet, value: T, index: i32, array: TArray) => TRet,
initialValue: TRet
): TRet {
var index = <i32>array.length - 1;
var length = -1;
while (index != length) {
initialValue = callbackfn(
initialValue,
unchecked(array[index]),
index,
array,
);
--index;
}
return initialValue;
}

View File

@ -11,7 +11,7 @@ import {
} from "./internal/string";
import {
storeUnsafe as storeUnsafeArray
STORE
} from "./internal/arraybuffer";
@sealed
@ -436,7 +436,7 @@ export class String {
),
HEADER_SIZE
);
storeUnsafeArray<String,String>(buffer, i, char);
STORE<String>(buffer, i, char);
}
return result;
} else if (!length) {

View File

@ -1,52 +1,77 @@
import {
TypedArray
TypedArray,
FILL,
SORT,
SUBARRAY,
REDUCE,
REDUCE_RIGHT
} from "./internal/typedarray";
export class Int8Array extends TypedArray<i8,i32> {
import {
defaultComparator
} from "./internal/array";
export class Int8Array extends TypedArray<i8> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<i8>();
fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int8Array {
return FILL<Int8Array, i8>(this, value, start, end);
}
sort(comparator: (a: i8, b: i8) => i32 = defaultComparator<i8>()): Int8Array {
return SORT<Int8Array, i8>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Int8Array {
return changetype<Int8Array>(super.subarray(begin, end));
return SUBARRAY<Int8Array, i8>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i8, index: i32, array: Int8Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int8Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: i8, index: i32, array: Int8Array) => T,
initialValue: T,
): T {
return REDUCE<Int8Array, i8, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i8, index: i32, array: Int8Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int8Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: i8, index: i32, array: Int8Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Int8Array, i8, T>(this, callbackfn, initialValue);
}
}
export class Uint8Array extends TypedArray<u8,u32> {
export class Uint8Array extends TypedArray<u8> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u8>();
fill(value: u32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint8Array {
return FILL<Uint8Array, u8>(this, value, start, end);
}
sort(comparator: (a: u8, b: u8) => i32 = defaultComparator<u8>()): Uint8Array {
return SORT<Uint8Array, u8>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint8Array {
return changetype<Uint8Array>(super.subarray(begin, end));
return SUBARRAY<Uint8Array, u8>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u8, index: i32, array: Uint8Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint8Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: u8, index: i32, array: Uint8Array) => T,
initialValue: T,
): T {
return REDUCE<Uint8Array, u8, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u8, index: i32, array: Uint8Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint8Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: u8, index: i32, array: Uint8Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Uint8Array, u8, T>(this, callbackfn, initialValue);
}
}
export class Uint8ClampedArray extends TypedArray<u8,u32> {
export class Uint8ClampedArray extends Uint8Array {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u8>();
@inline @operator("[]=")
@ -58,202 +83,244 @@ export class Uint8ClampedArray extends TypedArray<u8,u32> {
protected __unchecked_set(index: i32, value: i32): void {
super.__unchecked_set(index, max(min(value, 255), 0));
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint8ClampedArray {
return changetype<Uint8ClampedArray>(super.subarray(begin, end));
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u8, index: i32, array: Uint8ClampedArray) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint8ClampedArray, ReturnType>(callbackfn, this, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u8, index: i32, array: Uint8ClampedArray) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint8ClampedArray, ReturnType>(callbackfn, this, initialValue, true);
}
}
export class Int16Array extends TypedArray<i16,i32> {
export class Int16Array extends TypedArray<i16> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<i16>();
fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int16Array {
return FILL<Int16Array, i16>(this, value, start, end);
}
sort(comparator: (a: i16, b: i16) => i32 = defaultComparator<i16>()): Int16Array {
return SORT<Int16Array, i16>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Int16Array {
return changetype<Int16Array>(super.subarray(begin, end));
return SUBARRAY<Int16Array, i16>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i16, index: i32, array: Int16Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int16Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: i16, index: i32, array: Int16Array) => T,
initialValue: T,
): T {
return REDUCE<Int16Array, i16, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i16, index: i32, array: Int16Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int16Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: i16, index: i32, array: Int16Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Int16Array, i16, T>(this, callbackfn, initialValue);
}
}
export class Uint16Array extends TypedArray<u16,u32> {
export class Uint16Array extends TypedArray<u16> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u16>();
fill(value: u32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint16Array {
return FILL<Uint16Array, u16>(this, value, start, end);
}
sort(comparator: (a: u16, b: u16) => i32 = defaultComparator<u16>()): Uint16Array {
return SORT<Uint16Array, u16>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint16Array {
return changetype<Uint16Array>(super.subarray(begin, end));
return SUBARRAY<Uint16Array, u16>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u16, index: i32, array: Uint16Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint16Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: u16, index: i32, array: Uint16Array) => T,
initialValue: T,
): T {
return REDUCE<Uint16Array, u16, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u16, index: i32, array: Uint16Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint16Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: u16, index: i32, array: Uint16Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Uint16Array, u16, T>(this, callbackfn, initialValue);
}
}
export class Int32Array extends TypedArray<i32,i32> {
export class Int32Array extends TypedArray<i32> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<i32>();
fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int32Array {
return FILL<Int32Array, i32>(this, value, start, end);
}
sort(comparator: (a: i32, b: i32) => i32 = defaultComparator<i32>()): Int32Array {
return SORT<Int32Array, i32>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Int32Array {
return changetype<Int32Array>(super.subarray(begin, end));
return SUBARRAY<Int32Array, i32>(this, begin, end);
}
/**
* @param callbackfn {function} - a function that reduces each value to a ReturnType
* @param initialValue {ReturnType} - the initial ReturnType value to be passed to the callbackfn
*/
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i32, index: i32, array: Int32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int32Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: i32, index: i32, array: Int32Array) => T,
initialValue: T,
): T {
return REDUCE<Int32Array, i32, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i32, index: i32, array: Int32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int32Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: i32, index: i32, array: Int32Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Int32Array, i32, T>(this, callbackfn, initialValue);
}
}
export class Uint32Array extends TypedArray<u32,u32> {
export class Uint32Array extends TypedArray<u32> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u32>();
fill(value: u32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint32Array {
return FILL<Uint32Array, u32>(this, value, start, end);
}
sort(comparator: (a: u32, b: u32) => i32 = defaultComparator<u32>()): Uint32Array {
return SORT<Uint32Array, u32>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint32Array {
return changetype<Uint32Array>(super.subarray(begin, end));
return SUBARRAY<Uint32Array, u32>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u32, index: i32, array: Uint32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint32Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: u32, index: i32, array: Uint32Array) => T,
initialValue: T,
): T {
return REDUCE<Uint32Array, u32, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u32, index: i32, array: Uint32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint32Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: u32, index: i32, array: Uint32Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Uint32Array, u32, T>(this, callbackfn, initialValue);
}
}
export class Int64Array extends TypedArray<i64,i64> {
export class Int64Array extends TypedArray<i64> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<i64>();
fill(value: i64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int64Array {
return FILL<Int64Array, i64>(this, value, start, end);
}
sort(comparator: (a: i64, b: i64) => i32 = defaultComparator<i64>()): Int64Array {
return SORT<Int64Array, i64>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Int64Array {
return changetype<Int64Array>(super.subarray(begin, end));
return SUBARRAY<Int64Array, i64>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i64, index: i32, array: Int64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int64Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: i64, index: i32, array: Int64Array) => T,
initialValue: T,
): T {
return REDUCE<Int64Array, i64, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i64, index: i32, array: Int64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int64Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: i64, index: i32, array: Int64Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Int64Array, i64, T>(this, callbackfn, initialValue);
}
}
export class Uint64Array extends TypedArray<u64,u64> {
export class Uint64Array extends TypedArray<u64> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u64>();
fill(value: u64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint64Array {
return FILL<Uint64Array, u64>(this, value, start, end);
}
sort(comparator: (a: u64, b: u64) => i32 = defaultComparator<u64>()): Uint64Array {
return SORT<Uint64Array, u64>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint64Array {
return changetype<Uint64Array>(super.subarray(begin, end));
return SUBARRAY<Uint64Array, u64>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u64, index: i32, array: Uint64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint64Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: u64, index: i32, array: Uint64Array) => T,
initialValue: T,
): T {
return REDUCE<Uint64Array, u64, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u64, index: i32, array: Uint64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint64Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: u64, index: i32, array: Uint64Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Uint64Array, u64, T>(this, callbackfn, initialValue);
}
}
export class Float32Array extends TypedArray<f32,f32> {
export class Float32Array extends TypedArray<f32> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<f32>();
fill(value: f32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Float32Array {
return FILL<Float32Array, f32>(this, value, start, end);
}
sort(comparator: (a: f32, b: f32) => i32 = defaultComparator<f32>()): Float32Array {
return SORT<Float32Array, f32>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Float32Array {
return changetype<Float32Array>(super.subarray(begin, end));
return SUBARRAY<Float32Array, f32>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: f32, index: i32, array: Float32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Float32Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: f32, index: i32, array: Float32Array) => T,
initialValue: T,
): T {
return REDUCE<Float32Array, f32, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: f32, index: i32, array: Float32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Float32Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: f32, index: i32, array: Float32Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Float32Array, f32, T>(this, callbackfn, initialValue);
}
}
export class Float64Array extends TypedArray<f64,f64> {
export class Float64Array extends TypedArray<f64> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<f64>();
fill(value: f64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Float64Array {
return FILL<Float64Array, f64>(this, value, start, end);
}
sort(comparator: (a: f64, b: f64) => i32 = defaultComparator<f64>()): Float64Array {
return SORT<Float64Array, f64>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Float64Array {
return changetype<Float64Array>(super.subarray(begin, end));
return SUBARRAY<Float64Array, f64>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: f64, index: i32, array: Float64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Float64Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: f64, index: i32, array: Float64Array) => T,
initialValue: T,
): T {
return REDUCE<Float64Array, f64, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: f64, index: i32, array: Float64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Float64Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: f64, index: i32, array: Float64Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Float64Array, f64, T>(this, callbackfn, initialValue);
}
}

View File

@ -0,0 +1,91 @@
(module
(type $ii (func (param i32) (result i32)))
(type $v (func))
(memory $0 0)
(table $0 1 anyfunc)
(elem (i32.const 0) $null)
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $optional-typeparameters/tConcrete (mut i32) (i32.const 0))
(global $optional-typeparameters/tDerived (mut i32) (i32.const 0))
(export "memory" (memory $0))
(export "table" (table $0))
(start $start)
(func $~lib/allocator/arena/__memory_allocate (; 0 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.const 1073741824
i32.gt_u
if
unreachable
end
get_global $~lib/allocator/arena/offset
tee_local $1
get_local $0
i32.const 1
get_local $0
i32.const 1
i32.gt_u
select
i32.add
i32.const 7
i32.add
i32.const -8
i32.and
tee_local $2
current_memory
tee_local $3
i32.const 16
i32.shl
i32.gt_u
if
get_local $3
get_local $2
get_local $1
i32.sub
i32.const 65535
i32.add
i32.const -65536
i32.and
i32.const 16
i32.shr_u
tee_local $0
get_local $3
get_local $0
i32.gt_s
select
grow_memory
i32.const 0
i32.lt_s
if
get_local $0
grow_memory
i32.const 0
i32.lt_s
if
unreachable
end
end
end
get_local $2
set_global $~lib/allocator/arena/offset
get_local $1
)
(func $start (; 1 ;) (type $v)
i32.const 8
set_global $~lib/allocator/arena/startOffset
get_global $~lib/allocator/arena/startOffset
set_global $~lib/allocator/arena/offset
i32.const 0
call $~lib/allocator/arena/__memory_allocate
set_global $optional-typeparameters/tConcrete
i32.const 0
call $~lib/allocator/arena/__memory_allocate
set_global $optional-typeparameters/tDerived
)
(func $null (; 2 ;) (type $v)
nop
)
)

View File

@ -0,0 +1,28 @@
function testConcrete<T,U = i32>(a: T): U {
return a;
}
function testDerived<T,U = T>(a: T): U {
return a;
}
testConcrete<i32>(1);
testDerived<i32>(2);
class TestConcrete<T,U = i32> {
test<V = i32>(a: T, b: U): V {
return a + b;
}
}
class TestDerived<T,U = T> {
test<V = U>(a: T, b: U): V {
return a + b;
}
}
import "allocator/arena";
var tConcrete = new TestConcrete<i32>();
tConcrete.test<i32>(1, 2);
var tDerived = new TestDerived<f64>()
tDerived.test<f64>(1, 2);

View File

@ -0,0 +1,166 @@
(module
(type $ii (func (param i32) (result i32)))
(type $iiii (func (param i32 i32 i32) (result i32)))
(type $iFFF (func (param i32 f64 f64) (result f64)))
(type $v (func))
(memory $0 0)
(table $0 1 anyfunc)
(elem (i32.const 0) $null)
(global $~lib/internal/allocator/AL_BITS i32 (i32.const 3))
(global $~lib/internal/allocator/AL_SIZE i32 (i32.const 8))
(global $~lib/internal/allocator/AL_MASK i32 (i32.const 7))
(global $~lib/internal/allocator/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $optional-typeparameters/tConcrete (mut i32) (i32.const 0))
(global $optional-typeparameters/tDerived (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 8))
(export "memory" (memory $0))
(export "table" (table $0))
(start $start)
(func $optional-typeparameters/testConcrete<i32,i32> (; 0 ;) (type $ii) (param $0 i32) (result i32)
get_local $0
)
(func $optional-typeparameters/testDerived<i32,i32> (; 1 ;) (type $ii) (param $0 i32) (result i32)
get_local $0
)
(func $~lib/allocator/arena/__memory_allocate (; 2 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
get_local $0
get_global $~lib/internal/allocator/MAX_SIZE_32
i32.gt_u
if
unreachable
end
get_global $~lib/allocator/arena/offset
set_local $1
get_local $1
get_local $0
tee_local $2
i32.const 1
tee_local $3
get_local $2
get_local $3
i32.gt_u
select
i32.add
get_global $~lib/internal/allocator/AL_MASK
i32.add
get_global $~lib/internal/allocator/AL_MASK
i32.const -1
i32.xor
i32.and
set_local $4
current_memory
set_local $5
get_local $4
get_local $5
i32.const 16
i32.shl
i32.gt_u
if
get_local $4
get_local $1
i32.sub
i32.const 65535
i32.add
i32.const 65535
i32.const -1
i32.xor
i32.and
i32.const 16
i32.shr_u
set_local $2
get_local $5
tee_local $3
get_local $2
tee_local $6
get_local $3
get_local $6
i32.gt_s
select
set_local $3
get_local $3
grow_memory
i32.const 0
i32.lt_s
if
get_local $2
grow_memory
i32.const 0
i32.lt_s
if
unreachable
end
end
end
get_local $4
set_global $~lib/allocator/arena/offset
get_local $1
)
(func $~lib/memory/memory.allocate (; 3 ;) (type $ii) (param $0 i32) (result i32)
get_local $0
call $~lib/allocator/arena/__memory_allocate
return
)
(func $optional-typeparameters/TestConcrete<i32,i32>#test<i32> (; 4 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
get_local $1
get_local $2
i32.add
)
(func $optional-typeparameters/TestDerived<f64,f64>#test<f64> (; 5 ;) (type $iFFF) (param $0 i32) (param $1 f64) (param $2 f64) (result f64)
get_local $1
get_local $2
f64.add
)
(func $start (; 6 ;) (type $v)
(local $0 i32)
i32.const 1
call $optional-typeparameters/testConcrete<i32,i32>
drop
i32.const 2
call $optional-typeparameters/testDerived<i32,i32>
drop
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
block (result i32)
i32.const 0
call $~lib/memory/memory.allocate
set_local $0
get_local $0
end
set_global $optional-typeparameters/tConcrete
get_global $optional-typeparameters/tConcrete
i32.const 1
i32.const 2
call $optional-typeparameters/TestConcrete<i32,i32>#test<i32>
drop
block (result i32)
i32.const 0
call $~lib/memory/memory.allocate
set_local $0
get_local $0
end
set_global $optional-typeparameters/tDerived
get_global $optional-typeparameters/tDerived
f64.const 1
f64.const 2
call $optional-typeparameters/TestDerived<f64,f64>#test<f64>
drop
)
(func $null (; 7 ;) (type $v)
)
)

View File

@ -27,6 +27,7 @@
(export "stringArrayArrayMethodCall" (func $std/array-access/stringArrayArrayMethodCall))
(func $~lib/array/Array<Array<i32>>#__get (; 1 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -37,11 +38,15 @@
i32.shr_u
i32.lt_u
if (result i32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 2
i32.shl
i32.add
get_local $3
i32.add
i32.load offset=8
else
unreachable
@ -49,6 +54,7 @@
)
(func $~lib/array/Array<i32>#__get (; 2 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -59,11 +65,15 @@
i32.shr_u
i32.lt_u
if (result i32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 2
i32.shl
i32.add
get_local $3
i32.add
i32.load offset=8
else
unreachable
@ -78,6 +88,7 @@
)
(func $~lib/array/Array<String>#__get (; 4 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -88,11 +99,15 @@
i32.shr_u
i32.lt_u
if (result i32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 2
i32.shl
i32.add
get_local $3
i32.add
i32.load offset=8
else
unreachable
@ -234,6 +249,7 @@
)
(func $~lib/array/Array<Array<String>>#__get (; 9 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -244,11 +260,15 @@
i32.shr_u
i32.lt_u
if (result i32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 2
i32.shl
i32.add
get_local $3
i32.add
i32.load offset=8
else
unreachable

View File

@ -39,6 +39,7 @@
(start $start)
(func $~lib/array/Array<i8>#__get (; 1 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -49,11 +50,15 @@
i32.shr_u
i32.lt_u
if (result i32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 0
i32.shl
i32.add
get_local $3
i32.add
i32.load8_s offset=8
else
unreachable
@ -61,6 +66,7 @@
)
(func $~lib/array/Array<i32>#__get (; 2 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -71,11 +77,15 @@
i32.shr_u
i32.lt_u
if (result i32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 2
i32.shl
i32.add
get_local $3
i32.add
i32.load offset=8
else
unreachable
@ -471,7 +481,7 @@
if
i32.const 0
i32.const 136
i32.const 45
i32.const 46
i32.const 39
call $~lib/env/abort
unreachable
@ -521,14 +531,19 @@
)
(func $~lib/array/Array<i8>#__unchecked_set (; 9 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
get_local $0
i32.load
set_local $3
i32.const 0
set_local $4
get_local $3
get_local $1
i32.const 0
i32.shl
i32.add
get_local $4
i32.add
get_local $2
i32.store8 offset=8
)
@ -543,7 +558,7 @@
if
i32.const 0
i32.const 136
i32.const 45
i32.const 46
i32.const 39
call $~lib/env/abort
unreachable
@ -593,14 +608,19 @@
)
(func $~lib/array/Array<i32>#__unchecked_set (; 11 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
get_local $0
i32.load
set_local $3
i32.const 0
set_local $4
get_local $3
get_local $1
i32.const 2
i32.shl
i32.add
get_local $4
i32.add
get_local $2
i32.store offset=8
)
@ -615,7 +635,7 @@
if
i32.const 0
i32.const 136
i32.const 45
i32.const 46
i32.const 39
call $~lib/env/abort
unreachable
@ -665,14 +685,19 @@
)
(func $~lib/array/Array<Ref>#__unchecked_set (; 13 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
get_local $0
i32.load
set_local $3
i32.const 0
set_local $4
get_local $3
get_local $1
i32.const 2
i32.shl
i32.add
get_local $4
i32.add
get_local $2
i32.store offset=8
)
@ -703,7 +728,7 @@
if
i32.const 0
i32.const 136
i32.const 45
i32.const 46
i32.const 39
call $~lib/env/abort
unreachable
@ -753,14 +778,19 @@
)
(func $~lib/array/Array<RefWithCtor>#__unchecked_set (; 16 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
get_local $0
i32.load
set_local $3
i32.const 0
set_local $4
get_local $3
get_local $1
i32.const 2
i32.shl
i32.add
get_local $4
i32.add
get_local $2
i32.store offset=8
)

View File

@ -729,7 +729,7 @@
if
i32.const 0
i32.const 8
i32.const 45
i32.const 46
i32.const 39
call $~lib/env/abort
unreachable
@ -997,10 +997,10 @@
i32.ge_s
i32.eqz
if
get_local $6
get_local $2
i32.const 2
i32.shl
get_local $6
i32.add
get_local $1
i32.store offset=8
@ -2344,7 +2344,7 @@
if
i32.const 0
i32.const 8
i32.const 184
i32.const 185
i32.const 42
call $~lib/env/abort
unreachable
@ -2361,10 +2361,10 @@
get_local $0
get_local $3
i32.store offset=4
get_local $4
get_local $2
i32.const 2
i32.shl
get_local $4
i32.add
get_local $1
i32.store offset=8
@ -2381,7 +2381,7 @@
if
i32.const 0
i32.const 8
i32.const 246
i32.const 247
i32.const 20
call $~lib/env/abort
unreachable
@ -2582,15 +2582,15 @@
loop $continue|0
get_local $3
if
get_local $6
get_local $1
i32.const 2
i32.shl
get_local $6
i32.add
get_local $6
get_local $2
i32.const 2
i32.shl
get_local $6
i32.add
i32.load offset=8
i32.store offset=8
@ -2679,7 +2679,7 @@
if
i32.const 0
i32.const 8
i32.const 336
i32.const 337
i32.const 42
call $~lib/env/abort
unreachable
@ -2731,7 +2731,7 @@
if
i32.const 0
i32.const 8
i32.const 307
i32.const 308
i32.const 20
call $~lib/env/abort
unreachable
@ -2784,29 +2784,29 @@
get_local $2
i32.ge_s
br_if $break|0
get_local $3
get_local $1
i32.const 2
i32.shl
get_local $3
i32.add
i32.load offset=8
set_local $4
get_local $3
get_local $1
i32.const 2
i32.shl
get_local $3
i32.add
get_local $3
get_local $2
i32.const 2
i32.shl
get_local $3
i32.add
i32.load offset=8
i32.store offset=8
get_local $3
get_local $2
i32.const 2
i32.shl
get_local $3
i32.add
get_local $4
i32.store offset=8
@ -2866,10 +2866,10 @@
get_local $4
i32.lt_s
if
get_local $0
get_local $2
i32.const 2
i32.shl
get_local $0
i32.add
i32.load offset=8
get_local $1
@ -3019,7 +3019,7 @@
if
i32.const 0
i32.const 8
i32.const 109
i32.const 110
i32.const 41
call $~lib/env/abort
unreachable
@ -3039,10 +3039,10 @@
get_local $4
i32.store offset=4
end
get_local $3
get_local $1
i32.const 2
i32.shl
get_local $3
i32.add
get_local $2
i32.store offset=8
@ -3080,10 +3080,10 @@
br_if $break|0
i32.const 3
set_global $~argc
get_local $4
get_local $2
i32.const 2
i32.shl
get_local $4
i32.add
i32.load offset=8
get_local $2
@ -3166,10 +3166,10 @@
br_if $break|0
i32.const 3
set_global $~argc
get_local $4
get_local $2
i32.const 2
i32.shl
get_local $4
i32.add
i32.load offset=8
get_local $2
@ -3252,10 +3252,10 @@
br_if $break|0
i32.const 3
set_global $~argc
get_local $4
get_local $2
i32.const 2
i32.shl
get_local $4
i32.add
i32.load offset=8
get_local $2
@ -3339,10 +3339,10 @@
br_if $break|0
i32.const 3
set_global $~argc
get_local $4
get_local $2
i32.const 2
i32.shl
get_local $4
i32.add
i32.load offset=8
get_local $2
@ -3483,15 +3483,15 @@
br_if $break|0
i32.const 3
set_global $~argc
get_local $2
i32.const 2
i32.shl
get_local $7
i32.add
get_local $2
i32.const 2
i32.shl
i32.add
get_local $4
get_local $2
i32.const 2
i32.shl
i32.add
i32.load offset=8
get_local $2
@ -3561,10 +3561,10 @@
get_local $3
i32.eqz
br_if $break|0
get_local $5
get_local $2
i32.const 2
i32.shl
get_local $5
i32.add
i32.load offset=8
set_local $3
@ -3659,10 +3659,10 @@
i32.const 4
set_global $~argc
get_local $2
get_local $5
get_local $3
i32.const 2
i32.shl
get_local $5
i32.add
i32.load offset=8
get_local $3
@ -3736,10 +3736,10 @@
i32.const 4
set_global $~argc
get_local $2
get_local $4
get_local $3
i32.const 2
i32.shl
get_local $4
i32.add
i32.load offset=8
get_local $3
@ -4074,14 +4074,12 @@
get_local $3
i32.const 2
i32.shl
tee_local $1
get_local $0
i32.add
tee_local $1
f32.load offset=8
f32.store offset=8
get_local $0
get_local $1
i32.add
get_local $6
f32.store offset=8
i32.const 1
@ -4183,12 +4181,11 @@
get_local $0
i32.const 4
i32.add
tee_local $2
tee_local $1
f32.load offset=8
set_local $6
get_local $2
get_local $1
get_local $0
tee_local $1
f32.load offset=8
f32.store offset=8
get_local $0
@ -4205,7 +4202,7 @@
if
i32.const 0
i32.const 8
i32.const 408
i32.const 409
i32.const 4
call $~lib/env/abort
unreachable
@ -4648,14 +4645,12 @@
get_local $3
i32.const 3
i32.shl
tee_local $1
get_local $0
i32.add
tee_local $1
f64.load offset=8
f64.store offset=8
get_local $0
get_local $1
i32.add
get_local $6
f64.store offset=8
i32.const 1
@ -4757,12 +4752,11 @@
get_local $0
i32.const 8
i32.add
tee_local $2
tee_local $1
f64.load offset=8
set_local $6
get_local $2
get_local $1
get_local $0
tee_local $1
f64.load offset=8
f64.store offset=8
get_local $0
@ -4779,7 +4773,7 @@
if
i32.const 0
i32.const 8
i32.const 408
i32.const 409
i32.const 4
call $~lib/env/abort
unreachable
@ -5106,19 +5100,19 @@
get_local $1
i32.const 1
i32.sub
set_local $4
set_local $3
loop $repeat|0
get_local $4
get_local $3
i32.const 0
i32.gt_s
if
get_local $4
set_local $3
get_local $3
set_local $4
loop $continue|1
get_local $3
get_local $4
i32.const 1
i32.and
get_local $3
get_local $4
i32.const 6
i32.shr_s
i32.const 2
@ -5126,7 +5120,7 @@
get_local $7
i32.add
i32.load
get_local $3
get_local $4
i32.const 1
i32.shr_s
i32.const 31
@ -5136,14 +5130,14 @@
i32.and
i32.eq
if
get_local $3
get_local $4
i32.const 1
i32.shr_s
set_local $3
set_local $4
br $continue|1
end
end
get_local $3
get_local $4
i32.const 1
i32.shr_s
tee_local $5
@ -5152,8 +5146,8 @@
get_local $0
i32.add
i32.load offset=8
set_local $3
get_local $4
set_local $4
get_local $3
i32.const 2
i32.shl
get_local $0
@ -5162,14 +5156,14 @@
set_local $6
i32.const 2
set_global $~argc
get_local $3
get_local $4
get_local $6
get_local $2
call_indirect (type $iii)
i32.const 0
i32.lt_s
if
get_local $4
get_local $3
i32.const 5
i32.shr_s
i32.const 2
@ -5180,18 +5174,18 @@
get_local $8
i32.load
i32.const 1
get_local $4
get_local $3
i32.const 31
i32.and
i32.shl
i32.xor
i32.store
get_local $4
get_local $3
i32.const 2
i32.shl
get_local $0
i32.add
get_local $3
get_local $4
i32.store offset=8
get_local $5
i32.const 2
@ -5201,19 +5195,19 @@
get_local $6
i32.store offset=8
end
get_local $4
get_local $3
i32.const 1
i32.sub
set_local $4
set_local $3
br $repeat|0
end
end
get_local $1
i32.const 1
i32.sub
set_local $4
set_local $3
loop $repeat|2
get_local $4
get_local $3
i32.const 2
i32.ge_s
if
@ -5221,17 +5215,15 @@
i32.load offset=8
set_local $6
get_local $0
get_local $4
get_local $3
i32.const 2
i32.shl
tee_local $1
get_local $0
i32.add
tee_local $1
i32.load offset=8
i32.store offset=8
get_local $0
get_local $1
i32.add
get_local $6
i32.store offset=8
i32.const 1
@ -5255,11 +5247,11 @@
i32.const 1
i32.shl
i32.add
tee_local $3
get_local $4
tee_local $4
get_local $3
i32.lt_s
if
get_local $3
get_local $4
set_local $5
br $continue|3
end
@ -5278,11 +5270,11 @@
get_local $0
i32.add
i32.load offset=8
set_local $3
set_local $4
i32.const 2
set_global $~argc
get_local $6
get_local $3
get_local $4
get_local $2
call_indirect (type $iii)
i32.const 0
@ -5313,7 +5305,7 @@
get_local $6
i32.store offset=8
get_local $0
get_local $3
get_local $4
i32.store offset=8
end
get_local $5
@ -5323,22 +5315,21 @@
br $continue|4
end
end
get_local $4
get_local $3
i32.const 1
i32.sub
set_local $4
set_local $3
br $repeat|2
end
end
get_local $0
i32.const 4
i32.add
tee_local $3
tee_local $2
i32.load offset=8
set_local $1
get_local $3
get_local $2
get_local $0
tee_local $2
i32.load offset=8
i32.store offset=8
get_local $0
@ -5354,7 +5345,7 @@
if
i32.const 0
i32.const 8
i32.const 408
i32.const 409
i32.const 4
call $~lib/env/abort
unreachable
@ -5743,7 +5734,7 @@
if
i32.const 0
i32.const 8
i32.const 408
i32.const 409
i32.const 4
call $~lib/env/abort
unreachable
@ -6639,20 +6630,20 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $4
i32.const 100
i32.div_u
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
get_local $3
get_local $4
i32.const 100
i32.rem_u
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
i64.const 32
@ -6682,10 +6673,10 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $4
i32.const 2
i32.shl
get_local $3
i32.add
i32.load offset=8
i32.store offset=4
@ -6701,10 +6692,10 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $1
i32.const 2
i32.shl
get_local $3
i32.add
i32.load offset=8
i32.store offset=4
@ -7283,10 +7274,10 @@
get_local $9
i32.add
set_global $~lib/internal/number/_K
get_local $12
get_local $9
i32.const 2
i32.shl
get_local $12
i32.add
i64.load32_u offset=8
get_local $11
@ -7412,12 +7403,12 @@
get_local $9
i32.add
set_global $~lib/internal/number/_K
get_local $12
i32.const 0
get_local $9
i32.sub
i32.const 2
i32.shl
get_local $12
i32.add
i64.load32_u offset=8
get_local $8
@ -7430,9 +7421,9 @@
i32.shl
get_local $0
i32.add
tee_local $4
tee_local $7
i32.load16_u offset=4
set_local $7
set_local $4
loop $continue|4
get_local $1
get_local $8
@ -7470,10 +7461,10 @@
end
get_local $2
if
get_local $7
get_local $4
i32.const 1
i32.sub
set_local $7
set_local $4
get_local $1
get_local $10
i64.add
@ -7481,8 +7472,8 @@
br $continue|4
end
end
get_local $4
get_local $7
get_local $4
i32.store16 offset=4
get_local $6
else
@ -7888,10 +7879,10 @@
i32.add
i64.load offset=8
set_global $~lib/internal/number/_frc_pow
get_local $4
get_local $5
i32.const 1
i32.shl
get_local $4
i32.add
i32.load16_s offset=8
set_global $~lib/internal/number/_exp_pow
@ -8368,10 +8359,10 @@
get_local $2
i32.ge_s
br_if $break|0
get_local $6
get_local $0
i32.const 2
i32.shl
get_local $6
i32.add
i32.load offset=8
i32.load
@ -8402,10 +8393,10 @@
get_local $5
i32.ge_s
br_if $break|1
get_local $6
get_local $3
i32.const 2
i32.shl
get_local $6
i32.add
i32.load offset=8
tee_local $4
@ -8443,10 +8434,10 @@
br $repeat|1
end
end
get_local $6
get_local $5
i32.const 2
i32.shl
get_local $6
i32.add
i32.load offset=8
tee_local $4
@ -8504,20 +8495,22 @@
i32.add
tee_local $7
call $~lib/internal/string/allocateUnsafe
set_local $2
i32.const 0
set_local $0
loop $repeat|0
get_local $2
get_local $0
get_local $3
i32.lt_s
if
get_local $2
get_local $0
i32.const 2
i32.shl
get_local $5
i32.add
i32.load offset=8
if
get_local $0
get_local $2
get_local $1
i32.const 6792
i32.const 0
@ -8530,7 +8523,7 @@
end
get_local $6
if
get_local $0
get_local $2
get_local $1
i32.const 4136
i32.const 0
@ -8541,10 +8534,10 @@
i32.add
set_local $1
end
get_local $2
get_local $0
i32.const 1
i32.add
set_local $2
set_local $0
br $repeat|0
end
end
@ -8555,7 +8548,7 @@
i32.add
i32.load offset=8
if
get_local $0
get_local $2
get_local $1
i32.const 6792
i32.const 0
@ -8566,17 +8559,17 @@
i32.add
set_local $1
end
get_local $0
set_local $2
get_local $2
set_local $0
get_local $7
get_local $1
i32.gt_s
if
get_local $0
get_local $2
get_local $1
call $~lib/string/String#substring
set_local $2
get_local $0
set_local $0
get_local $2
i32.eqz
if
i32.const 0
@ -8587,7 +8580,7 @@
unreachable
end
end
get_local $2
get_local $0
)
(func $~lib/internal/number/itoa_stream<i8> (; 128 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)
@ -8999,6 +8992,7 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $4
i32.const 10000
i32.rem_u
@ -9007,15 +9001,14 @@
i32.div_u
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
get_local $3
get_local $4
i32.const 100
i32.rem_u
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
i64.const 32
@ -9030,16 +9023,16 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $6
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
get_local $3
get_local $5
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
i64.const 32
@ -9869,10 +9862,10 @@
get_local $4
i32.ge_s
br_if $break|0
get_local $5
get_local $0
i32.const 2
i32.shl
get_local $5
i32.add
i32.load offset=8
tee_local $3
@ -9898,10 +9891,10 @@
br $repeat|0
end
end
get_local $5
get_local $4
i32.const 2
i32.shl
get_local $5
i32.add
i32.load offset=8
tee_local $3

File diff suppressed because it is too large Load Diff

View File

@ -339,7 +339,7 @@
end
end
)
(func $~lib/internal/typedarray/TypedArray<u8,u32>#constructor (; 4 ;) (type $FUNCSIG$i) (result i32)
(func $~lib/internal/typedarray/TypedArray<u8>#constructor (; 4 ;) (type $FUNCSIG$i) (result i32)
(local $0 i32)
(local $1 i32)
i32.const 8
@ -371,7 +371,7 @@
i32.store offset=8
get_local $0
)
(func $~lib/internal/typedarray/TypedArray<u8,u32>#__set (; 5 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(func $~lib/internal/typedarray/TypedArray<u8>#__set (; 5 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
get_local $1
get_local $0
i32.load offset=8
@ -379,16 +379,16 @@
if
i32.const 0
i32.const 8
i32.const 54
i32.const 51
i32.const 63
call $~lib/env/abort
unreachable
end
get_local $0
i32.load offset=4
get_local $1
get_local $0
i32.load
get_local $0
i32.load offset=4
i32.add
i32.add
get_local $2
@ -1092,40 +1092,40 @@
set_global $~lib/allocator/arena/startOffset
get_global $~lib/allocator/arena/startOffset
set_global $~lib/allocator/arena/offset
call $~lib/internal/typedarray/TypedArray<u8,u32>#constructor
call $~lib/internal/typedarray/TypedArray<u8>#constructor
set_global $std/dataview/array
get_global $std/dataview/array
i32.const 0
i32.const 246
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 1
i32.const 224
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 2
i32.const 88
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 3
i32.const 159
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 4
i32.const 130
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 5
i32.const 101
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 6
i32.const 67
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 7
i32.const 95
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.load
get_global $std/dataview/array

View File

@ -415,7 +415,7 @@
call $~lib/allocator/arena/__memory_allocate
return
)
(func $~lib/internal/typedarray/TypedArray<u8,u32>#constructor (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(func $~lib/internal/typedarray/TypedArray<u8>#constructor (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
@ -426,7 +426,7 @@
if
i32.const 0
i32.const 8
i32.const 27
i32.const 24
i32.const 34
call $~lib/env/abort
unreachable
@ -480,7 +480,7 @@
i32.store offset=8
get_local $0
)
(func $~lib/internal/typedarray/TypedArray<u8,u32>#__set (; 7 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(func $~lib/internal/typedarray/TypedArray<u8>#__set (; 7 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
get_local $1
@ -492,7 +492,7 @@
if
i32.const 0
i32.const 8
i32.const 54
i32.const 51
i32.const 63
call $~lib/env/abort
unreachable
@ -504,12 +504,12 @@
i32.load offset=4
set_local $4
get_local $3
get_local $4
i32.add
get_local $1
i32.const 0
i32.shl
i32.add
get_local $4
i32.add
get_local $2
i32.store8 offset=8
)
@ -1703,40 +1703,40 @@
set_global $~lib/allocator/arena/offset
i32.const 0
i32.const 8
call $~lib/internal/typedarray/TypedArray<u8,u32>#constructor
call $~lib/internal/typedarray/TypedArray<u8>#constructor
set_global $std/dataview/array
get_global $std/dataview/array
i32.const 0
i32.const 246
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 1
i32.const 224
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 2
i32.const 88
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 3
i32.const 159
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 4
i32.const 130
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 5
i32.const 101
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 6
i32.const 67
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
get_global $std/dataview/array
i32.const 7
i32.const 95
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
call $~lib/internal/typedarray/TypedArray<u8>#__set
i32.const 0
get_global $std/dataview/array
i32.load

View File

@ -1900,7 +1900,7 @@
if
i32.const 0
i32.const 72
i32.const 109
i32.const 110
i32.const 41
call $~lib/env/abort
unreachable
@ -1920,10 +1920,10 @@
get_local $4
i32.store offset=4
end
get_local $3
get_local $1
i32.const 2
i32.shl
get_local $3
i32.add
get_local $2
i32.store offset=8

View File

@ -2412,6 +2412,7 @@
(func $~lib/array/Array<Foo>#__set (; 28 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
get_local $0
i32.load
set_local $3
@ -2430,7 +2431,7 @@
if
i32.const 0
i32.const 72
i32.const 109
i32.const 110
i32.const 41
call $~lib/env/abort
unreachable
@ -2452,11 +2453,15 @@
i32.add
i32.store offset=4
end
i32.const 0
set_local $5
get_local $3
get_local $1
i32.const 2
i32.shl
i32.add
get_local $5
i32.add
get_local $2
i32.store offset=8
get_local $0

View File

@ -43,6 +43,7 @@
(start $start)
(func $~lib/array/Array<i32>#__get (; 1 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -53,11 +54,15 @@
i32.shr_u
i32.lt_u
if (result i32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 2
i32.shl
i32.add
get_local $3
i32.add
i32.load offset=8
else
unreachable
@ -1978,6 +1983,7 @@
(func $~lib/array/Array<i32>#__set (; 9 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
get_local $0
i32.load
set_local $3
@ -1996,7 +2002,7 @@
if
i32.const 0
i32.const 184
i32.const 109
i32.const 110
i32.const 41
call $~lib/env/abort
unreachable
@ -2018,16 +2024,21 @@
i32.add
i32.store offset=4
end
i32.const 0
set_local $5
get_local $3
get_local $1
i32.const 2
i32.shl
i32.add
get_local $5
i32.add
get_local $2
i32.store offset=8
)
(func $~lib/array/Array<i64>#__get (; 10 ;) (type $iiI) (param $0 i32) (param $1 i32) (result i64)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -2038,11 +2049,15 @@
i32.shr_u
i32.lt_u
if (result i64)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 3
i32.shl
i32.add
get_local $3
i32.add
i64.load offset=8
else
unreachable
@ -2051,6 +2066,7 @@
(func $~lib/array/Array<i64>#__set (; 11 ;) (type $iiIv) (param $0 i32) (param $1 i32) (param $2 i64)
(local $3 i32)
(local $4 i32)
(local $5 i32)
get_local $0
i32.load
set_local $3
@ -2069,7 +2085,7 @@
if
i32.const 0
i32.const 184
i32.const 109
i32.const 110
i32.const 41
call $~lib/env/abort
unreachable
@ -2091,16 +2107,21 @@
i32.add
i32.store offset=4
end
i32.const 0
set_local $5
get_local $3
get_local $1
i32.const 3
i32.shl
i32.add
get_local $5
i32.add
get_local $2
i64.store offset=8
)
(func $~lib/array/Array<f32>#__get (; 12 ;) (type $iif) (param $0 i32) (param $1 i32) (result f32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -2111,11 +2132,15 @@
i32.shr_u
i32.lt_u
if (result f32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 2
i32.shl
i32.add
get_local $3
i32.add
f32.load offset=8
else
unreachable
@ -2124,6 +2149,7 @@
(func $~lib/array/Array<f32>#__set (; 13 ;) (type $iifv) (param $0 i32) (param $1 i32) (param $2 f32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
get_local $0
i32.load
set_local $3
@ -2142,7 +2168,7 @@
if
i32.const 0
i32.const 184
i32.const 109
i32.const 110
i32.const 41
call $~lib/env/abort
unreachable
@ -2164,16 +2190,21 @@
i32.add
i32.store offset=4
end
i32.const 0
set_local $5
get_local $3
get_local $1
i32.const 2
i32.shl
i32.add
get_local $5
i32.add
get_local $2
f32.store offset=8
)
(func $~lib/array/Array<f64>#__get (; 14 ;) (type $iiF) (param $0 i32) (param $1 i32) (result f64)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -2184,11 +2215,15 @@
i32.shr_u
i32.lt_u
if (result f64)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 3
i32.shl
i32.add
get_local $3
i32.add
f64.load offset=8
else
unreachable
@ -2197,6 +2232,7 @@
(func $~lib/array/Array<f64>#__set (; 15 ;) (type $iiFv) (param $0 i32) (param $1 i32) (param $2 f64)
(local $3 i32)
(local $4 i32)
(local $5 i32)
get_local $0
i32.load
set_local $3
@ -2215,7 +2251,7 @@
if
i32.const 0
i32.const 184
i32.const 109
i32.const 110
i32.const 41
call $~lib/env/abort
unreachable
@ -2237,11 +2273,15 @@
i32.add
i32.store offset=4
end
i32.const 0
set_local $5
get_local $3
get_local $1
i32.const 3
i32.shl
i32.add
get_local $5
i32.add
get_local $2
f64.store offset=8
)

View File

@ -3304,7 +3304,7 @@
if
i32.const 0
i32.const 976
i32.const 45
i32.const 46
i32.const 39
call $~lib/env/abort
unreachable
@ -3452,7 +3452,7 @@
if
i32.const 0
i32.const 976
i32.const 184
i32.const 185
i32.const 42
call $~lib/env/abort
unreachable
@ -3469,10 +3469,10 @@
get_local $0
get_local $3
i32.store offset=4
get_local $4
get_local $2
i32.const 2
i32.shl
get_local $4
i32.add
get_local $1
i32.store offset=8
@ -3787,20 +3787,20 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $4
i32.const 100
i32.div_u
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
get_local $3
get_local $4
i32.const 100
i32.rem_u
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
i64.const 32
@ -3830,10 +3830,10 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $4
i32.const 2
i32.shl
get_local $3
i32.add
i32.load offset=8
i32.store offset=4
@ -3849,10 +3849,10 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $1
i32.const 2
i32.shl
get_local $3
i32.add
i32.load offset=8
i32.store offset=4
@ -4022,6 +4022,7 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $4
i32.const 10000
i32.rem_u
@ -4030,15 +4031,14 @@
i32.div_u
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
get_local $3
get_local $4
i32.const 100
i32.rem_u
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
i64.const 32
@ -4053,16 +4053,16 @@
i32.shl
get_local $0
i32.add
get_local $3
get_local $6
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
get_local $3
get_local $5
i32.const 2
i32.shl
get_local $3
i32.add
i64.load32_u offset=8
i64.const 32
@ -4374,10 +4374,10 @@
get_local $9
i32.add
set_global $~lib/internal/number/_K
get_local $12
get_local $9
i32.const 2
i32.shl
get_local $12
i32.add
i64.load32_u offset=8
get_local $11
@ -4503,12 +4503,12 @@
get_local $9
i32.add
set_global $~lib/internal/number/_K
get_local $12
i32.const 0
get_local $9
i32.sub
i32.const 2
i32.shl
get_local $12
i32.add
i64.load32_u offset=8
get_local $8
@ -4521,9 +4521,9 @@
i32.shl
get_local $0
i32.add
tee_local $4
tee_local $7
i32.load16_u offset=4
set_local $7
set_local $4
loop $continue|4
get_local $1
get_local $8
@ -4561,10 +4561,10 @@
end
get_local $2
if
get_local $7
get_local $4
i32.const 1
i32.sub
set_local $7
set_local $4
get_local $1
get_local $10
i64.add
@ -4572,8 +4572,8 @@
br $continue|4
end
end
get_local $4
get_local $7
get_local $4
i32.store16 offset=4
get_local $6
else
@ -4979,10 +4979,10 @@
i32.add
i64.load offset=8
set_global $~lib/internal/number/_frc_pow
get_local $4
get_local $5
i32.const 1
i32.shl
get_local $4
i32.add
i32.load16_s offset=8
set_global $~lib/internal/number/_exp_pow

View File

@ -4103,7 +4103,7 @@
if
i32.const 0
i32.const 976
i32.const 45
i32.const 46
i32.const 39
call $~lib/env/abort
unreachable
@ -4153,14 +4153,19 @@
)
(func $~lib/array/Array<String>#__unchecked_set (; 39 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
get_local $0
i32.load
set_local $3
i32.const 0
set_local $4
get_local $3
get_local $1
i32.const 2
i32.shl
i32.add
get_local $4
i32.add
get_local $2
i32.store offset=8
)
@ -4279,6 +4284,7 @@
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
get_local $0
i32.load offset=4
set_local $2
@ -4304,7 +4310,7 @@
if
i32.const 0
i32.const 976
i32.const 184
i32.const 185
i32.const 42
call $~lib/env/abort
unreachable
@ -4322,11 +4328,15 @@
get_local $0
get_local $5
i32.store offset=4
i32.const 0
set_local $6
get_local $3
get_local $2
i32.const 2
i32.shl
i32.add
get_local $6
i32.add
get_local $1
i32.store offset=8
get_local $5
@ -4344,6 +4354,7 @@
(local $12 i32)
(local $13 i32)
(local $14 i32)
(local $15 i32)
get_local $0
i32.const 0
i32.ne
@ -4442,11 +4453,15 @@
i32.add
i32.load16_u offset=4
i32.store16 offset=4
i32.const 0
set_local $9
get_local $6
get_local $7
i32.const 2
i32.shl
i32.add
get_local $9
i32.add
get_local $8
i32.store offset=8
end
@ -4472,26 +4487,26 @@
i32.const 0
i32.const 0
call $~lib/array/Array<String>#constructor
set_local $9
i32.const 0
set_local $10
i32.const 0
set_local $11
i32.const 0
set_local $12
i32.const 0
set_local $13
block $break|1
loop $continue|1
get_local $0
get_local $1
get_local $11
get_local $12
call $~lib/string/String#indexOf
tee_local $10
tee_local $11
i32.const -1
i32.ne
if
block
get_local $10
get_local $11
get_local $12
i32.sub
set_local $6
get_local $6
@ -4504,82 +4519,82 @@
get_local $3
i32.const 0
get_local $0
get_local $11
get_local $12
get_local $6
call $~lib/internal/string/copyUnsafe
get_local $9
get_local $10
get_local $3
call $~lib/array/Array<String>#push
drop
else
get_local $9
get_local $10
i32.const 256
call $~lib/array/Array<String>#push
drop
end
get_local $12
get_local $13
i32.const 1
i32.add
tee_local $12
tee_local $13
get_local $2
i32.eq
if
get_local $9
get_local $10
return
end
get_local $10
get_local $11
get_local $5
i32.add
set_local $11
set_local $12
end
br $continue|1
end
end
end
get_local $11
get_local $12
i32.eqz
if
block (result i32)
i32.const 0
i32.const 1
call $~lib/array/Array<String>#constructor
set_local $13
get_local $13
set_local $14
get_local $14
i32.const 0
get_local $0
call $~lib/array/Array<String>#__unchecked_set
get_local $13
get_local $14
end
return
end
get_local $4
get_local $11
get_local $12
i32.sub
set_local $14
get_local $14
set_local $15
get_local $15
i32.const 0
i32.gt_s
if
get_local $14
get_local $15
call $~lib/internal/string/allocateUnsafe
set_local $13
get_local $13
set_local $14
get_local $14
i32.const 0
get_local $0
get_local $11
get_local $14
get_local $12
get_local $15
call $~lib/internal/string/copyUnsafe
get_local $9
get_local $13
get_local $10
get_local $14
call $~lib/array/Array<String>#push
drop
else
get_local $9
get_local $10
i32.const 256
call $~lib/array/Array<String>#push
drop
end
get_local $9
get_local $10
)
(func $~lib/string/String#split|trampoline (; 43 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
block $2of2
@ -4604,6 +4619,7 @@
)
(func $~lib/array/Array<String>#__get (; 44 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
get_local $0
i32.load
set_local $2
@ -4614,11 +4630,15 @@
i32.shr_u
i32.lt_u
if (result i32)
i32.const 0
set_local $3
get_local $2
get_local $1
i32.const 2
i32.shl
i32.add
get_local $3
i32.add
i32.load offset=8
else
unreachable
@ -4699,8 +4719,9 @@
(local $5 i32)
(local $6 i32)
(local $7 i32)
(local $8 i64)
(local $8 i32)
(local $9 i64)
(local $10 i64)
block $~lib/internal/number/DIGITS|inlined.0 (result i32)
i32.const 1720
end
@ -4731,24 +4752,32 @@
i32.const 100
i32.rem_u
set_local $7
block $~lib/internal/arraybuffer/loadUnsafe<u32,u64>|inlined.0 (result i64)
block $~lib/internal/arraybuffer/LOAD<u32,u64>|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 $8
block $~lib/internal/arraybuffer/loadUnsafe<u32,u64>|inlined.1 (result i64)
set_local $9
block $~lib/internal/arraybuffer/LOAD<u32,u64>|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 $9
set_local $10
get_local $2
i32.const 4
i32.sub
@ -4758,8 +4787,8 @@
i32.const 1
i32.shl
i32.add
get_local $8
get_local $9
get_local $10
i64.const 32
i64.shl
i64.or
@ -4787,12 +4816,16 @@
i32.const 2
i32.sub
set_local $2
block $~lib/internal/arraybuffer/loadUnsafe<u32,u32>|inlined.0 (result i32)
block $~lib/internal/arraybuffer/LOAD<u32,u32>|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
@ -4812,12 +4845,16 @@
i32.const 2
i32.sub
set_local $2
block $~lib/internal/arraybuffer/loadUnsafe<u32,u32>|inlined.1 (result i32)
block $~lib/internal/arraybuffer/LOAD<u32,u32>|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
@ -4987,8 +5024,9 @@
(local $9 i32)
(local $10 i32)
(local $11 i32)
(local $12 i64)
(local $12 i32)
(local $13 i64)
(local $14 i64)
block $~lib/internal/number/DIGITS|inlined.1 (result i32)
i32.const 2512
end
@ -5038,24 +5076,32 @@
i32.const 100
i32.rem_u
set_local $11
block $~lib/internal/arraybuffer/loadUnsafe<u32,u64>|inlined.2 (result i64)
block $~lib/internal/arraybuffer/LOAD<u32,u64>|inlined.2 (result i64)
i32.const 0
set_local $12
get_local $3
get_local $10
i32.const 2
i32.shl
i32.add
get_local $12
i32.add
i64.load32_u offset=8
end
set_local $12
block $~lib/internal/arraybuffer/loadUnsafe<u32,u64>|inlined.3 (result i64)
set_local $13
block $~lib/internal/arraybuffer/LOAD<u32,u64>|inlined.3 (result i64)
i32.const 0
set_local $12
get_local $3
get_local $11
i32.const 2
i32.shl
i32.add
get_local $12
i32.add
i64.load32_u offset=8
end
set_local $13
set_local $14
get_local $2
i32.const 4
i32.sub
@ -5065,30 +5111,38 @@
i32.const 1
i32.shl
i32.add
get_local $12
get_local $13
get_local $14
i64.const 32
i64.shl
i64.or
i64.store offset=4
block $~lib/internal/arraybuffer/loadUnsafe<u32,u64>|inlined.4 (result i64)
block $~lib/internal/arraybuffer/LOAD<u32,u64>|inlined.4 (result i64)
i32.const 0
set_local $12
get_local $3
get_local $8
i32.const 2
i32.shl
i32.add
get_local $12
i32.add
i64.load32_u offset=8
end
set_local $12
block $~lib/internal/arraybuffer/loadUnsafe<u32,u64>|inlined.5 (result i64)
set_local $13
block $~lib/internal/arraybuffer/LOAD<u32,u64>|inlined.5 (result i64)
i32.const 0
set_local $12
get_local $3
get_local $9
i32.const 2
i32.shl
i32.add
get_local $12
i32.add
i64.load32_u offset=8
end
set_local $13
set_local $14
get_local $2
i32.const 4
i32.sub
@ -5098,8 +5152,8 @@
i32.const 1
i32.shl
i32.add
get_local $12
get_local $13
get_local $14
i64.const 32
i64.shl
i64.or
@ -5539,12 +5593,16 @@
get_local $14
i32.add
set_global $~lib/internal/number/_K
block $~lib/internal/arraybuffer/loadUnsafe<u32,u64>|inlined.6 (result i64)
block $~lib/internal/arraybuffer/LOAD<u32,u64>|inlined.6 (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
@ -5689,16 +5747,20 @@
i32.add
set_global $~lib/internal/number/_K
get_local $10
block $~lib/internal/arraybuffer/loadUnsafe<u32,u64>|inlined.7 (result i64)
block $~lib/internal/arraybuffer/LOAD<u32,u64>|inlined.7 (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
@ -5710,10 +5772,10 @@
i32.const 1
i32.shl
i32.add
set_local $17
get_local $17
i32.load16_u offset=4
set_local $21
get_local $21
i32.load16_u offset=4
set_local $17
block $break|4
loop $continue|4
get_local $13
@ -5755,10 +5817,10 @@
end
if
block
get_local $21
get_local $17
i32.const 1
i32.sub
set_local $21
set_local $17
get_local $13
get_local $8
i64.add
@ -5768,8 +5830,8 @@
end
end
end
get_local $17
get_local $21
get_local $17
i32.store16 offset=4
get_local $15
return
@ -6138,7 +6200,7 @@
(local $11 f64)
(local $12 i32)
(local $13 i32)
(local $14 i64)
(local $14 i32)
(local $15 i64)
(local $16 i64)
(local $17 i64)
@ -6148,7 +6210,8 @@
(local $21 i64)
(local $22 i64)
(local $23 i64)
(local $24 i32)
(local $24 i64)
(local $25 i32)
get_local $1
f64.const 0
f64.lt
@ -6290,21 +6353,29 @@
end
i32.load
set_local $13
block $~lib/internal/arraybuffer/loadUnsafe<u64,u64>|inlined.0 (result i64)
block $~lib/internal/arraybuffer/LOAD<u64,u64>|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/loadUnsafe<i16,i32>|inlined.0 (result i32)
block $~lib/internal/arraybuffer/LOAD<i16,i32>|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
@ -6330,60 +6401,60 @@
get_local $6
i64.const 4294967295
i64.and
set_local $14
set_local $15
get_local $7
i64.const 4294967295
i64.and
set_local $15
set_local $16
get_local $6
i64.const 32
i64.shr_u
set_local $16
set_local $17
get_local $7
i64.const 32
i64.shr_u
set_local $17
get_local $14
get_local $15
i64.mul
set_local $18
get_local $16
get_local $15
get_local $16
i64.mul
get_local $18
set_local $19
get_local $17
get_local $16
i64.mul
get_local $19
i64.const 32
i64.shr_u
i64.add
set_local $19
get_local $14
get_local $17
set_local $20
get_local $15
get_local $18
i64.mul
get_local $19
get_local $20
i64.const 4294967295
i64.and
i64.add
set_local $20
get_local $20
set_local $21
get_local $21
i64.const 2147483647
i64.add
set_local $20
get_local $19
i64.const 32
i64.shr_u
set_local $19
set_local $21
get_local $20
i64.const 32
i64.shr_u
set_local $20
get_local $16
get_local $21
i64.const 32
i64.shr_u
set_local $21
get_local $17
get_local $18
i64.mul
get_local $19
i64.add
get_local $20
i64.add
get_local $21
i64.add
end
set_local $20
set_local $21
block $~lib/internal/number/umul64e|inlined.0 (result i32)
get_local $4
get_local $12
@ -6394,66 +6465,66 @@
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 $19
get_local $7
i64.const 4294967295
i64.and
set_local $18
get_local $7
i64.const 4294967295
i64.and
get_local $20
i64.const 32
i64.shr_u
set_local $17
get_local $19
get_local $7
i64.const 32
i64.shr_u
set_local $16
get_local $7
i64.const 32
i64.shr_u
set_local $15
get_local $19
get_local $18
get_local $17
i64.mul
set_local $14
get_local $16
set_local $15
get_local $17
get_local $18
i64.mul
get_local $14
get_local $15
i64.const 32
i64.shr_u
i64.add
set_local $21
get_local $18
get_local $15
set_local $22
get_local $19
get_local $16
i64.mul
get_local $21
get_local $22
i64.const 4294967295
i64.and
i64.add
set_local $22
get_local $22
set_local $23
get_local $23
i64.const 2147483647
i64.add
set_local $22
get_local $21
i64.const 32
i64.shr_u
set_local $21
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
get_local $15
i64.mul
get_local $21
i64.add
get_local $22
i64.add
get_local $23
i64.add
end
i64.const 1
i64.sub
set_local $22
set_local $23
block $~lib/internal/number/umul64e|inlined.1 (result i32)
get_global $~lib/internal/number/_exp
set_local $9
@ -6466,92 +6537,92 @@
set_local $9
block $~lib/internal/number/umul64f|inlined.2 (result i64)
get_global $~lib/internal/number/_frc_minus
set_local $21
get_local $21
i64.const 4294967295
i64.and
set_local $14
get_local $7
set_local $22
get_local $22
i64.const 4294967295
i64.and
set_local $15
get_local $21
i64.const 32
i64.shr_u
set_local $16
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 $14
get_local $15
i64.mul
get_local $7
i64.const 32
i64.shr_u
set_local $18
get_local $16
get_local $15
get_local $16
i64.mul
get_local $18
set_local $19
get_local $17
get_local $16
i64.mul
get_local $19
i64.const 32
i64.shr_u
i64.add
set_local $19
get_local $14
get_local $17
set_local $20
get_local $15
get_local $18
i64.mul
get_local $19
get_local $20
i64.const 4294967295
i64.and
i64.add
set_local $23
get_local $23
set_local $24
get_local $24
i64.const 2147483647
i64.add
set_local $23
get_local $19
set_local $24
get_local $20
i64.const 32
i64.shr_u
set_local $19
get_local $23
set_local $20
get_local $24
i64.const 32
i64.shr_u
set_local $23
get_local $16
set_local $24
get_local $17
get_local $18
i64.mul
get_local $19
get_local $20
i64.add
get_local $23
get_local $24
i64.add
end
i64.const 1
i64.add
set_local $23
get_local $22
set_local $24
get_local $23
get_local $24
i64.sub
set_local $19
set_local $20
get_local $0
get_local $20
get_local $21
get_local $8
get_local $22
get_local $23
get_local $9
get_local $19
get_local $20
get_local $2
call $~lib/internal/number/genDigits
end
set_local $24
set_local $25
get_local $0
get_local $2
i32.const 1
i32.shl
i32.add
get_local $24
get_local $25
get_local $2
i32.sub
get_global $~lib/internal/number/_K
call $~lib/internal/number/prettify
set_local $24
get_local $24
set_local $25
get_local $25
get_local $2
i32.add
)

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,6 @@ assert(Uint64Array.BYTES_PER_ELEMENT == 8);
assert(Float32Array.BYTES_PER_ELEMENT == 4);
assert(Float64Array.BYTES_PER_ELEMENT == 8);
function isInt8ArrayEqual(a: Int8Array, b: Array<i8>): bool {
if (a.length != b.length) return false;
for (let i = 0, len = a.length; i < len; i++) {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
class A {
[key: i32]: f64;
}

View File

@ -0,0 +1,3 @@
class A {
[key: i32]: f64;
}

View File

@ -0,0 +1,3 @@
function a<T=i32>(): T { return 0; }
function a<T,U=i32>(): T { return 0; }
function a<T,U=i32,V>(): T { return 0; } // ERROR 2706

View File

@ -0,0 +1,10 @@
function a<T=i32>(): T {
return 0;
}
function a<T, U=i32>(): T {
return 0;
}
function a<T, U=i32, V>(): T {
return 0;
}
// ERROR 2706: "Required type parameters may not follow optional type parameters." in optional-typeparameters.ts:3:19