mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-26 07:22:21 +00:00
Elements can be namespaces; Static properties and methods
This commit is contained in:
parent
b69c07af45
commit
8085a02df3
@ -7,8 +7,6 @@ AssemblyScript NEXT
|
|||||||
|
|
||||||
By compiling syntactially (not necessarily semantically) valid TypeScript to [Binaryen](https://github.com/WebAssembly/binaryen) IR, the resulting module can be validated, optimized, emitted in WebAssembly text or binary format and converted to [asm.js](http://asmjs.org) as a polyfill.
|
By compiling syntactially (not necessarily semantically) valid TypeScript to [Binaryen](https://github.com/WebAssembly/binaryen) IR, the resulting module can be validated, optimized, emitted in WebAssembly text or binary format and converted to [asm.js](http://asmjs.org) as a polyfill.
|
||||||
|
|
||||||
The compiler itself utilizes "portable definitions" so it can be compiled to both JavaScript using `tsc` and, eventually, to WebAssembly using `asc`.
|
|
||||||
|
|
||||||
Note, though, that this version of the compiler (0.5.0, NEXT) is relatively new and does not yet support some features a TypeScript programmer might expect, e.g., strings, arrays and classes.
|
Note, though, that this version of the compiler (0.5.0, NEXT) is relatively new and does not yet support some features a TypeScript programmer might expect, e.g., strings, arrays and classes.
|
||||||
|
|
||||||
See [the AssemblyScript wiki](https://github.com/AssemblyScript/assemblyscript/wiki) for additional information and documentation.
|
See [the AssemblyScript wiki](https://github.com/AssemblyScript/assemblyscript/wiki) for additional information and documentation.
|
||||||
|
135
src/compiler.ts
135
src/compiler.ts
@ -419,52 +419,56 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
if (element.isCompiled)
|
if (element.isCompiled)
|
||||||
return;
|
return;
|
||||||
let previousValue: EnumValue | null = null;
|
let previousValue: EnumValue | null = null;
|
||||||
for (let [key, val] of element.members) {
|
if (element.members)
|
||||||
if (val.hasConstantValue) {
|
for (let [key, member] of element.members) {
|
||||||
this.module.addGlobal(val.internalName, NativeType.I32, false, this.module.createI32(val.constantValue));
|
if (member.kind != ElementKind.ENUMVALUE)
|
||||||
} else if (val.declaration) {
|
continue;
|
||||||
const declaration: EnumValueDeclaration = val.declaration;
|
const val: EnumValue = <EnumValue>member;
|
||||||
let initializer: ExpressionRef;
|
if (val.hasConstantValue) {
|
||||||
let initializeInStart: bool = false;
|
this.module.addGlobal(val.internalName, NativeType.I32, false, this.module.createI32(val.constantValue));
|
||||||
if (declaration.value) {
|
} else if (val.declaration) {
|
||||||
initializer = this.compileExpression(<Expression>declaration.value, Type.i32);
|
const declaration: EnumValueDeclaration = val.declaration;
|
||||||
if (_BinaryenExpressionGetId(initializer) != ExpressionId.Const) {
|
let initializer: ExpressionRef;
|
||||||
initializer = this.precomputeExpressionRef(initializer);
|
let initializeInStart: bool = false;
|
||||||
|
if (declaration.value) {
|
||||||
|
initializer = this.compileExpression(<Expression>declaration.value, Type.i32);
|
||||||
if (_BinaryenExpressionGetId(initializer) != ExpressionId.Const) {
|
if (_BinaryenExpressionGetId(initializer) != ExpressionId.Const) {
|
||||||
if (element.isConstant)
|
initializer = this.precomputeExpressionRef(initializer);
|
||||||
this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, declaration.range);
|
if (_BinaryenExpressionGetId(initializer) != ExpressionId.Const) {
|
||||||
initializeInStart = true;
|
if (element.isConstant)
|
||||||
|
this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, declaration.range);
|
||||||
|
initializeInStart = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if (previousValue == null) {
|
||||||
|
initializer = this.module.createI32(0);
|
||||||
|
} else if (previousValue.hasConstantValue) {
|
||||||
|
initializer = this.module.createI32(previousValue.constantValue + 1);
|
||||||
|
} else {
|
||||||
|
// in TypeScript this errors with TS1061, but actually we can do:
|
||||||
|
initializer = this.module.createBinary(BinaryOp.AddI32,
|
||||||
|
this.module.createGetGlobal(previousValue.internalName, NativeType.I32),
|
||||||
|
this.module.createI32(1)
|
||||||
|
);
|
||||||
|
if (element.isConstant)
|
||||||
|
this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, declaration.range);
|
||||||
|
initializeInStart = true;
|
||||||
}
|
}
|
||||||
} else if (previousValue == null) {
|
if (initializeInStart) {
|
||||||
initializer = this.module.createI32(0);
|
this.module.addGlobal(val.internalName, NativeType.I32, true, this.module.createI32(0));
|
||||||
} else if (previousValue.hasConstantValue) {
|
this.startFunctionBody.push(this.module.createSetGlobal(val.internalName, initializer));
|
||||||
initializer = this.module.createI32(previousValue.constantValue + 1);
|
} else {
|
||||||
} else {
|
this.module.addGlobal(val.internalName, NativeType.I32, false, initializer);
|
||||||
// in TypeScript this errors with TS1061, but actually we can do:
|
if (_BinaryenExpressionGetType(initializer) == NativeType.I32) {
|
||||||
initializer = this.module.createBinary(BinaryOp.AddI32,
|
val.constantValue = _BinaryenConstGetValueI32(initializer);
|
||||||
this.module.createGetGlobal(previousValue.internalName, NativeType.I32),
|
val.hasConstantValue = true;
|
||||||
this.module.createI32(1)
|
} else
|
||||||
);
|
throw new Error("unexpected initializer type");
|
||||||
if (element.isConstant)
|
}
|
||||||
this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, val.declaration.range);
|
} else
|
||||||
initializeInStart = true;
|
throw new Error("unexpected missing declaration or constant value");
|
||||||
}
|
previousValue = <EnumValue>val;
|
||||||
if (initializeInStart) {
|
}
|
||||||
this.module.addGlobal(val.internalName, NativeType.I32, true, this.module.createI32(0));
|
|
||||||
this.startFunctionBody.push(this.module.createSetGlobal(val.internalName, initializer));
|
|
||||||
} else {
|
|
||||||
this.module.addGlobal(val.internalName, NativeType.I32, false, initializer);
|
|
||||||
if (_BinaryenExpressionGetType(initializer) == NativeType.I32) {
|
|
||||||
val.constantValue = _BinaryenConstGetValueI32(initializer);
|
|
||||||
val.hasConstantValue = true;
|
|
||||||
} else
|
|
||||||
throw new Error("unexpected initializer type");
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
throw new Error("unexpected missing declaration or constant value");
|
|
||||||
previousValue = val;
|
|
||||||
}
|
|
||||||
element.isCompiled = true;
|
element.isCompiled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,6 +588,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileNamespace(ns: Namespace): void {
|
compileNamespace(ns: Namespace): void {
|
||||||
|
if (!ns.members) return;
|
||||||
const noTreeShaking: bool = this.options.noTreeShaking;
|
const noTreeShaking: bool = this.options.noTreeShaking;
|
||||||
for (let [name, element] of ns.members) {
|
for (let [name, element] of ns.members) {
|
||||||
switch (element.kind) {
|
switch (element.kind) {
|
||||||
@ -1856,9 +1861,6 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let target: Element | null;
|
let target: Element | null;
|
||||||
switch (expression.kind) {
|
switch (expression.kind) {
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error("unexpected expression kind");
|
|
||||||
|
|
||||||
case NodeKind.THIS:
|
case NodeKind.THIS:
|
||||||
if (!this.currentFunction.instanceMethodOf) {
|
if (!this.currentFunction.instanceMethodOf) {
|
||||||
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range);
|
||||||
@ -1882,6 +1884,9 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
case NodeKind.PROPERTYACCESS:
|
case NodeKind.PROPERTYACCESS:
|
||||||
target = this.program.resolvePropertyAccess(<PropertyAccessExpression>expression, this.currentFunction); // reports
|
target = this.program.resolvePropertyAccess(<PropertyAccessExpression>expression, this.currentFunction); // reports
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error("unexpected expression kind");
|
||||||
}
|
}
|
||||||
if (!target)
|
if (!target)
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
@ -1891,20 +1896,29 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
let expr: ExpressionRef;
|
let expr: ExpressionRef;
|
||||||
switch (target.kind) {
|
switch (target.kind) {
|
||||||
|
|
||||||
// handle enum value right away
|
|
||||||
|
|
||||||
case ElementKind.ENUM:
|
case ElementKind.ENUM:
|
||||||
element = (<Enum>target).members.get(propertyName);
|
case ElementKind.CLASS_PROTOTYPE:
|
||||||
if (!element) {
|
case ElementKind.CLASS:
|
||||||
|
case ElementKind.NAMESPACE:
|
||||||
|
if (target.members) {
|
||||||
|
element = target.members.get(propertyName);
|
||||||
|
if (!element) {
|
||||||
|
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName);
|
||||||
|
return this.module.createUnreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle enum values right away
|
||||||
|
if (element.kind == ElementKind.ENUMVALUE) {
|
||||||
|
this.currentType = Type.i32;
|
||||||
|
return (<EnumValue>element).hasConstantValue
|
||||||
|
? this.module.createI32((<EnumValue>element).constantValue)
|
||||||
|
: this.module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName);
|
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName);
|
||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
this.currentType = Type.i32;
|
break;
|
||||||
return (<EnumValue>element).hasConstantValue
|
|
||||||
? this.module.createI32((<EnumValue>element).constantValue)
|
|
||||||
: this.module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
|
|
||||||
|
|
||||||
// postpone everything else
|
|
||||||
|
|
||||||
case ElementKind.LOCAL:
|
case ElementKind.LOCAL:
|
||||||
element = (<Local>target).type.classType;
|
element = (<Local>target).type.classType;
|
||||||
@ -1926,15 +1940,6 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
target = element;
|
target = element;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ElementKind.NAMESPACE:
|
|
||||||
element = (<Namespace>target).members.get(propertyName);
|
|
||||||
if (!(element && element.isExported)) {
|
|
||||||
this.error(DiagnosticCode.Namespace_0_has_no_exported_member_1, propertyAccess.property.range, (<Namespace>target).internalName, propertyName);
|
|
||||||
return this.module.createUnreachable();
|
|
||||||
}
|
|
||||||
target = element;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error("unexpected target kind");
|
throw new Error("unexpected target kind");
|
||||||
}
|
}
|
||||||
|
360
src/program.ts
360
src/program.ts
@ -210,94 +210,144 @@ export class Program extends DiagnosticEmitter {
|
|||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeClass(declaration: ClassDeclaration, namespace: Namespace | null = null): void {
|
private initializeClass(declaration: ClassDeclaration, namespace: Element | null = null): void {
|
||||||
throw new Error("not implemented");
|
const internalName: string = declaration.internalName;
|
||||||
/* const internalName: string = declaration.internalName;
|
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const prototype: ClassPrototype = new ClassPrototype(this, internalName, declaration);
|
const prototype: ClassPrototype = new ClassPrototype(this, internalName, declaration);
|
||||||
this.elements.set(internalName, prototype);
|
this.elements.set(internalName, prototype);
|
||||||
if (prototype.isExported) {
|
|
||||||
if (this.exports.has(internalName))
|
if (namespace) {
|
||||||
|
if (namespace.members) {
|
||||||
|
if (namespace.members.has(declaration.identifier.name)) {
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
namespace.members = new Map();
|
||||||
|
namespace.members.set(declaration.identifier.name, prototype);
|
||||||
|
} else if (prototype.isExported) {
|
||||||
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
return;
|
||||||
this.exports.set(internalName, prototype);
|
}
|
||||||
|
this.exports.set(internalName, prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
||||||
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
||||||
const memberDeclaration: DeclarationStatement = memberDeclarations[j];
|
switch (memberDeclarations[j].kind) {
|
||||||
if (memberDeclaration.kind == NodeKind.FIELD)
|
|
||||||
this.initializeField(<FieldDeclaration>memberDeclaration, prototype);
|
case NodeKind.FIELD:
|
||||||
else if (memberDeclaration.kind == NodeKind.METHOD)
|
this.initializeField(<FieldDeclaration>memberDeclarations[j], prototype);
|
||||||
this.initializeMethod(<MethodDeclaration>memberDeclaration, prototype);
|
break;
|
||||||
else
|
|
||||||
throw new Error("unexpected class member");
|
case NodeKind.METHOD:
|
||||||
} */
|
this.initializeMethod(<MethodDeclaration>memberDeclarations[j], prototype);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error("unexpected class member");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeField(declaration: FieldDeclaration, classPrototype: ClassPrototype): void {
|
private initializeField(declaration: FieldDeclaration, classPrototype: ClassPrototype): void {
|
||||||
throw new Error("not implemented");
|
const name: string = declaration.identifier.name;
|
||||||
/* const name: string = declaration.identifier.name;
|
|
||||||
if (classPrototype.members.has(name)) {
|
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) { // static fields become globals
|
|
||||||
const global: Global = new Global(this, internalName, declaration, null);
|
// static fields become global variables
|
||||||
classPrototype.members.set(name, global);
|
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
|
||||||
|
if (this.elements.has(internalName)) {
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (classPrototype.members) {
|
||||||
|
if (classPrototype.members.has(name)) {
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
classPrototype.members = new Map();
|
||||||
|
const staticField: Global = new Global(this, internalName, declaration, null);
|
||||||
|
classPrototype.members.set(name, staticField);
|
||||||
|
this.elements.set(internalName, staticField);
|
||||||
|
|
||||||
|
// instance fields are remembered until resolved
|
||||||
} else {
|
} else {
|
||||||
const field: FieldPrototype = new FieldPrototype(classPrototype, internalName, declaration);
|
if (classPrototype.instanceMembers) {
|
||||||
classPrototype.members.set(name, field);
|
if (classPrototype.instanceMembers.has(name)) {
|
||||||
} */
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
classPrototype.instanceMembers = new Map();
|
||||||
|
const instanceField = new FieldPrototype(classPrototype, internalName, declaration);
|
||||||
|
classPrototype.instanceMembers.set(name, instanceField);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
|
private initializeMethod(declaration: MethodDeclaration, classPrototype: ClassPrototype): void {
|
||||||
throw new Error("not implemented");
|
let name: string = declaration.identifier.name;
|
||||||
/* let name: string = declaration.identifier.name;
|
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (classPrototype.members.has(name)) {
|
|
||||||
|
// static methods become global functions
|
||||||
|
if (hasModifier(ModifierKind.STATIC, declaration.modifiers)) {
|
||||||
|
if (this.elements.has(internalName)) {
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (classPrototype.members) {
|
||||||
|
if (classPrototype.members.has(name)) {
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
classPrototype.members = new Map();
|
||||||
|
const staticPrototype: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, null);
|
||||||
|
classPrototype.members.set(name, staticPrototype);
|
||||||
|
this.elements.set(internalName, staticPrototype);
|
||||||
|
|
||||||
|
// instance methods are remembered until resolved
|
||||||
|
} else {
|
||||||
|
if (classPrototype.instanceMembers) {
|
||||||
|
if (classPrototype.instanceMembers.has(name)) {
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, declaration.internalName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
classPrototype.instanceMembers = new Map();
|
||||||
|
const instancePrototype: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, classPrototype);
|
||||||
|
classPrototype.instanceMembers.set(name, instancePrototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private initializeEnum(declaration: EnumDeclaration, namespace: Element | null = null): void {
|
||||||
|
const internalName: string = declaration.internalName;
|
||||||
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const func: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, hasModifier(ModifierKind.STATIC, declaration.modifiers) ? null : classPrototype);
|
|
||||||
let modifiers: Modifier[] | null;
|
|
||||||
if (modifiers = declaration.modifiers) {
|
|
||||||
for (let i: i32 = 0, k: i32 = modifiers.length; i < k; ++i) {
|
|
||||||
const modifier: Modifier = modifiers[i];
|
|
||||||
if (modifier.modifierKind == ModifierKind.GET) {
|
|
||||||
name = GETTER_PREFIX + name;
|
|
||||||
break;
|
|
||||||
} else if (modifier.modifierKind == ModifierKind.SET) {
|
|
||||||
name = SETTER_PREFIX + name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
classPrototype.members.set(name, func); */
|
|
||||||
}
|
|
||||||
|
|
||||||
private initializeEnum(declaration: EnumDeclaration, namespace: Namespace | null = null): void {
|
|
||||||
const internalName: string = declaration.internalName;
|
|
||||||
const enm: Enum = new Enum(this, internalName, declaration);
|
const enm: Enum = new Enum(this, internalName, declaration);
|
||||||
|
this.elements.set(internalName, enm);
|
||||||
if (this.elements.has(internalName))
|
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
|
||||||
else
|
|
||||||
this.elements.set(internalName, enm);
|
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members.has(declaration.identifier.name)) {
|
if (namespace.members) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
if (namespace.members.has(declaration.identifier.name)) {
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
namespace.members.set(declaration.identifier.name, enm);
|
namespace.members = new Map();
|
||||||
|
namespace.members.set(declaration.identifier.name, enm);
|
||||||
} else if (enm.isExported) {
|
} else if (enm.isExported) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
return;
|
||||||
this.exports.set(internalName, enm);
|
}
|
||||||
|
this.exports.set(internalName, enm);
|
||||||
}
|
}
|
||||||
|
|
||||||
const values: EnumValueDeclaration[] = declaration.members;
|
const values: EnumValueDeclaration[] = declaration.members;
|
||||||
@ -308,10 +358,13 @@ export class Program extends DiagnosticEmitter {
|
|||||||
private initializeEnumValue(declaration: EnumValueDeclaration, enm: Enum): void {
|
private initializeEnumValue(declaration: EnumValueDeclaration, enm: Enum): void {
|
||||||
const name: string = declaration.identifier.name;
|
const name: string = declaration.identifier.name;
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
if (enm.members.has(name)) {
|
if (enm.members) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
if (enm.members.has(name)) {
|
||||||
return;
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
enm.members = new Map();
|
||||||
const value: EnumValue = new EnumValue(enm, this, internalName, declaration);
|
const value: EnumValue = new EnumValue(enm, this, internalName, declaration);
|
||||||
enm.members.set(name, value);
|
enm.members.set(name, value);
|
||||||
}
|
}
|
||||||
@ -396,26 +449,30 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeFunction(declaration: FunctionDeclaration, namespace: Namespace | null = null): void {
|
private initializeFunction(declaration: FunctionDeclaration, namespace: Element | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const prototype: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, null);
|
|
||||||
|
|
||||||
if (this.elements.has(internalName)) {
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const prototype: FunctionPrototype = new FunctionPrototype(this, internalName, declaration, null);
|
||||||
this.elements.set(internalName, prototype);
|
this.elements.set(internalName, prototype);
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members.has(declaration.identifier.name))
|
if (namespace.members) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
if (namespace.members.has(declaration.identifier.name)) {
|
||||||
else
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
namespace.members.set(declaration.identifier.name, prototype);
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
namespace.members = new Map();
|
||||||
|
namespace.members.set(declaration.identifier.name, prototype);
|
||||||
} else if (prototype.isExported) {
|
} else if (prototype.isExported) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
return;
|
||||||
this.exports.set(internalName, prototype);
|
}
|
||||||
|
this.exports.set(internalName, prototype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,38 +529,43 @@ export class Program extends DiagnosticEmitter {
|
|||||||
queuedImports.push(queuedImport);
|
queuedImports.push(queuedImport);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeInterface(declaration: InterfaceDeclaration, namespace: Namespace | null = null): void {
|
private initializeInterface(declaration: InterfaceDeclaration, namespace: Element | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const prototype: InterfacePrototype = new InterfacePrototype(this, internalName, declaration);
|
const prototype: InterfacePrototype = new InterfacePrototype(this, internalName, declaration);
|
||||||
|
|
||||||
if (this.elements.has(internalName))
|
if (this.elements.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else
|
return;
|
||||||
this.elements.set(internalName, prototype);
|
}
|
||||||
|
this.elements.set(internalName, prototype);
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members.has(prototype.internalName))
|
if (namespace.members) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
if (namespace.members.has(prototype.internalName)) {
|
||||||
else
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
namespace.members.set(prototype.internalName, prototype);
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
namespace.members = new Map();
|
||||||
|
namespace.members.set(prototype.internalName, prototype);
|
||||||
} else if (prototype.isExported) {
|
} else if (prototype.isExported) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
return;
|
||||||
this.exports.set(internalName, prototype);
|
}
|
||||||
|
this.exports.set(internalName, prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
const memberDeclarations: DeclarationStatement[] = declaration.members;
|
||||||
for (let j: i32 = 0, l: i32 = memberDeclarations.length; j < l; ++j) {
|
for (let i: i32 = 0, k: i32 = memberDeclarations.length; i < k; ++i) {
|
||||||
const memberDeclaration: DeclarationStatement = memberDeclarations[j];
|
switch (memberDeclarations[i].kind) {
|
||||||
switch (memberDeclaration.kind) {
|
|
||||||
|
|
||||||
case NodeKind.FIELD:
|
case NodeKind.FIELD:
|
||||||
this.initializeField(<FieldDeclaration>memberDeclaration, prototype);
|
this.initializeField(<FieldDeclaration>memberDeclarations[i], prototype);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.METHOD:
|
case NodeKind.METHOD:
|
||||||
this.initializeMethod(<MethodDeclaration>memberDeclaration, prototype);
|
this.initializeMethod(<MethodDeclaration>memberDeclarations[i], prototype);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -512,54 +574,58 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeNamespace(declaration: NamespaceDeclaration, parentNamespace: Namespace | null = null): void {
|
private initializeNamespace(declaration: NamespaceDeclaration, parentNamespace: Element | null = null): void {
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const namespace: Namespace = new Namespace(this, internalName, declaration);
|
|
||||||
|
|
||||||
if (this.elements.has(internalName))
|
let namespace: Element | null = this.elements.get(internalName);
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
if (!namespace) {
|
||||||
else
|
namespace = new Namespace(this, internalName, declaration);
|
||||||
this.elements.set(internalName, namespace);
|
this.elements.set(internalName, namespace);
|
||||||
|
}
|
||||||
|
|
||||||
if (parentNamespace) {
|
if (parentNamespace) {
|
||||||
if (parentNamespace.members.has(declaration.identifier.name))
|
if (parentNamespace.members) {
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
if (parentNamespace.members.has(declaration.identifier.name)) {
|
||||||
else
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
parentNamespace.members.set(declaration.identifier.name, namespace);
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
parentNamespace.members = new Map();
|
||||||
|
parentNamespace.members.set(declaration.identifier.name, namespace);
|
||||||
} else if (namespace.isExported) {
|
} else if (namespace.isExported) {
|
||||||
if (this.exports.has(internalName))
|
if (this.exports.has(internalName)) {
|
||||||
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0, declaration.identifier.range, internalName);
|
||||||
else
|
return;
|
||||||
this.exports.set(internalName, namespace);
|
}
|
||||||
|
this.exports.set(internalName, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
const members: Statement[] = declaration.members;
|
const members: Statement[] = declaration.members;
|
||||||
for (let i: i32 = 0, k: i32 = members.length; i < k; ++i) {
|
for (let i: i32 = 0, k: i32 = members.length; i < k; ++i) {
|
||||||
const statement: Statement = members[i];
|
switch (members[i].kind) {
|
||||||
switch (statement.kind) {
|
|
||||||
|
|
||||||
case NodeKind.CLASS:
|
case NodeKind.CLASS:
|
||||||
this.initializeClass(<ClassDeclaration>statement, namespace);
|
this.initializeClass(<ClassDeclaration>members[i], namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.ENUM:
|
case NodeKind.ENUM:
|
||||||
this.initializeEnum(<EnumDeclaration>statement, namespace);
|
this.initializeEnum(<EnumDeclaration>members[i], namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.FUNCTION:
|
case NodeKind.FUNCTION:
|
||||||
this.initializeFunction(<FunctionDeclaration>statement, namespace);
|
this.initializeFunction(<FunctionDeclaration>members[i], namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.INTERFACE:
|
case NodeKind.INTERFACE:
|
||||||
this.initializeInterface(<InterfaceDeclaration>statement, namespace);
|
this.initializeInterface(<InterfaceDeclaration>members[i], namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.NAMESPACE:
|
case NodeKind.NAMESPACE:
|
||||||
this.initializeNamespace(<NamespaceDeclaration>statement, namespace);
|
this.initializeNamespace(<NamespaceDeclaration>members[i], namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.VARIABLE:
|
case NodeKind.VARIABLE:
|
||||||
this.initializeVariables(<VariableStatement>statement, namespace);
|
this.initializeVariables(<VariableStatement>members[i], namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -568,29 +634,33 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeVariables(statement: VariableStatement, namespace: Namespace | null = null): void {
|
private initializeVariables(statement: VariableStatement, namespace: Element | null = null): void {
|
||||||
const declarations: VariableDeclaration[] = statement.declarations;
|
const declarations: VariableDeclaration[] = statement.declarations;
|
||||||
for (let i: i32 = 0, k: i32 = declarations.length; i < k; ++i) {
|
for (let i: i32 = 0, k: i32 = declarations.length; i < k; ++i) {
|
||||||
const declaration: VariableDeclaration = declarations[i];
|
const declaration: VariableDeclaration = declarations[i];
|
||||||
const internalName: string = declaration.internalName;
|
const internalName: string = declaration.internalName;
|
||||||
const global: Global = new Global(this, internalName, declaration, null);
|
if (this.elements.has(internalName)) {
|
||||||
|
|
||||||
if (this.elements.has(internalName))
|
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else {
|
continue;
|
||||||
this.elements.set(internalName, global);
|
}
|
||||||
|
|
||||||
|
const global: Global = new Global(this, internalName, declaration, null);
|
||||||
|
this.elements.set(internalName, global);
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
if (namespace.members.has(declaration.identifier.name))
|
if (namespace.members) {
|
||||||
|
if (namespace.members.has(declaration.identifier.name)) {
|
||||||
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
namespace.members = new Map();
|
||||||
|
namespace.members.set(declaration.identifier.name, global);
|
||||||
|
} else if (global.isExported) {
|
||||||
|
if (this.exports.has(internalName))
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
||||||
else
|
else
|
||||||
namespace.members.set(declaration.identifier.name, global);
|
this.exports.set(internalName, global);
|
||||||
} else if (global.isExported) {
|
|
||||||
if (this.exports.has(internalName))
|
|
||||||
this.error(DiagnosticCode.Duplicate_identifier_0, declaration.identifier.range, internalName);
|
|
||||||
else
|
|
||||||
this.exports.set(internalName, global);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -683,17 +753,11 @@ export class Program extends DiagnosticEmitter {
|
|||||||
if (!target)
|
if (!target)
|
||||||
return null;
|
return null;
|
||||||
const propertyName: string = propertyAccess.property.name;
|
const propertyName: string = propertyAccess.property.name;
|
||||||
let member: Element | null = null;
|
if (target.members) {
|
||||||
if (target.kind == ElementKind.ENUM)
|
const member: Element | null = target.members.get(propertyName);
|
||||||
member = (<Enum>target).members.get(propertyName);
|
if (member)
|
||||||
else if (target.kind == ElementKind.NAMESPACE)
|
return member;
|
||||||
member = (<Namespace>target).members.get(propertyName);
|
}
|
||||||
// else if (target.kind == ElementKind.CLASS_PROTOTYPE)
|
|
||||||
// member = <Element | null>(<ClassPrototype>target).members.get(propertyName);
|
|
||||||
// else if (target.kind == ElementKind.CLASS)
|
|
||||||
// member = <Element | null>(<Class>target).members.get(propertyName);
|
|
||||||
if (member)
|
|
||||||
return member;
|
|
||||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, expression.range, (<PropertyAccessExpression>expression).property.name, target.internalName);
|
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, expression.range, (<PropertyAccessExpression>expression).property.name, target.internalName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -807,6 +871,8 @@ export abstract class Element {
|
|||||||
internalName: string;
|
internalName: string;
|
||||||
/** Element flags. */
|
/** Element flags. */
|
||||||
flags: ElementFlags = ElementFlags.NONE;
|
flags: ElementFlags = ElementFlags.NONE;
|
||||||
|
/** Namespaced member elements. */
|
||||||
|
members: Map<string,Element> | null = null;
|
||||||
|
|
||||||
/** Constructs a new element, linking it to its containing {@link Program}. */
|
/** Constructs a new element, linking it to its containing {@link Program}. */
|
||||||
protected constructor(program: Program, internalName: string) {
|
protected constructor(program: Program, internalName: string) {
|
||||||
@ -861,9 +927,7 @@ export class Namespace extends Element {
|
|||||||
kind = ElementKind.NAMESPACE;
|
kind = ElementKind.NAMESPACE;
|
||||||
|
|
||||||
/** Declaration reference. */
|
/** Declaration reference. */
|
||||||
declaration: NamespaceDeclaration | null;
|
declaration: NamespaceDeclaration | null; // more specific
|
||||||
/** Member elements. */
|
|
||||||
members: Map<string,Element> = new Map();
|
|
||||||
|
|
||||||
/** Constructs a new namespace. */
|
/** Constructs a new namespace. */
|
||||||
constructor(program: Program, internalName: string, declaration: NamespaceDeclaration | null = null) {
|
constructor(program: Program, internalName: string, declaration: NamespaceDeclaration | null = null) {
|
||||||
@ -882,18 +946,16 @@ export class Namespace extends Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** An enum. */
|
/** An enum. */
|
||||||
export class Enum extends Namespace {
|
export class Enum extends Element {
|
||||||
|
|
||||||
kind = ElementKind.ENUM;
|
kind = ElementKind.ENUM;
|
||||||
|
|
||||||
/** Declaration reference. */
|
/** Declaration reference. */
|
||||||
declaration: EnumDeclaration | null;
|
declaration: EnumDeclaration | null;
|
||||||
/** Enum members. */
|
|
||||||
members: Map<string,EnumValue> = new Map(); // more specific
|
|
||||||
|
|
||||||
/** Constructs a new enum. */
|
/** Constructs a new enum. */
|
||||||
constructor(program: Program, internalName: string, declaration: EnumDeclaration | null = null) {
|
constructor(program: Program, internalName: string, declaration: EnumDeclaration | null = null) {
|
||||||
super(program, internalName, null);
|
super(program, internalName);
|
||||||
if ((this.declaration = declaration) && this.declaration.modifiers) {
|
if ((this.declaration = declaration) && this.declaration.modifiers) {
|
||||||
for (let i: i32 = 0, k = this.declaration.modifiers.length; i < k; ++i) {
|
for (let i: i32 = 0, k = this.declaration.modifiers.length; i < k; ++i) {
|
||||||
switch (this.declaration.modifiers[i].modifierKind) {
|
switch (this.declaration.modifiers[i].modifierKind) {
|
||||||
@ -952,6 +1014,7 @@ export class Global extends Element {
|
|||||||
case ModifierKind.EXPORT: this.isExported = true; break;
|
case ModifierKind.EXPORT: this.isExported = true; break;
|
||||||
case ModifierKind.CONST: this.isConstant = true; break;
|
case ModifierKind.CONST: this.isConstant = true; break;
|
||||||
case ModifierKind.DECLARE: this.isDeclared = true; break;
|
case ModifierKind.DECLARE: this.isDeclared = true; break;
|
||||||
|
case ModifierKind.STATIC: break; // static fields become globals
|
||||||
default: throw new Error("unexpected modifier");
|
default: throw new Error("unexpected modifier");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1024,6 +1087,7 @@ export class FunctionPrototype extends Element {
|
|||||||
case ModifierKind.DECLARE: this.isDeclared = true; break;
|
case ModifierKind.DECLARE: this.isDeclared = true; break;
|
||||||
case ModifierKind.GET: this.isGetter = true; break;
|
case ModifierKind.GET: this.isGetter = true; break;
|
||||||
case ModifierKind.SET: this.isSetter = true; break;
|
case ModifierKind.SET: this.isSetter = true; break;
|
||||||
|
case ModifierKind.STATIC: break; // already handled
|
||||||
default: throw new Error("unexpected modifier");
|
default: throw new Error("unexpected modifier");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1314,14 +1378,8 @@ export class ClassPrototype extends Element {
|
|||||||
declaration: ClassDeclaration | null;
|
declaration: ClassDeclaration | null;
|
||||||
/** Resolved instances. */
|
/** Resolved instances. */
|
||||||
instances: Map<string,Class> = new Map();
|
instances: Map<string,Class> = new Map();
|
||||||
/** Static fields. */
|
/** Instance member prototypes. */
|
||||||
staticFields: Map<string,Global> | null = null;
|
instanceMembers: Map<string,Element> | null = null;
|
||||||
/** Static methods. */
|
|
||||||
staticMethods: Map<string,Function> | null = null;
|
|
||||||
/** Static getters. */
|
|
||||||
staticGetters: Map<string,Function> | null = null;
|
|
||||||
/** Static setters. */
|
|
||||||
staticSetters: Map<string,Function> | null = null;
|
|
||||||
|
|
||||||
constructor(program: Program, internalName: string, declaration: ClassDeclaration | null = null) {
|
constructor(program: Program, internalName: string, declaration: ClassDeclaration | null = null) {
|
||||||
super(program, internalName);
|
super(program, internalName);
|
||||||
|
@ -77,14 +77,20 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var expected = fs.readFileSync(__dirname + "/compiler/" + fixture, { encoding: "utf8" });
|
try {
|
||||||
var diffs = diff("compiler/" + fixture, expected, actual);
|
var expected = fs.readFileSync(__dirname + "/compiler/" + fixture, { encoding: "utf8" });
|
||||||
if (diffs !== null) {
|
var diffs = diff("compiler/" + fixture, expected, actual);
|
||||||
|
if (diffs !== null) {
|
||||||
|
process.exitCode = 1;
|
||||||
|
console.log(diffs);
|
||||||
|
console.log(chalk.default.red("diff ERROR"));
|
||||||
|
} else {
|
||||||
|
console.log(chalk.default.green("diff OK"));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
process.exitCode = 1;
|
process.exitCode = 1;
|
||||||
console.log(diffs);
|
console.log(e.message);
|
||||||
console.log(chalk.default.red("diff ERROR"));
|
console.log(chalk.default.red("diff ERROR"));
|
||||||
} else {
|
|
||||||
console.log(chalk.default.green("diff OK"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
tests/compiler/class.optimized-inlined.wast
Normal file
46
tests/compiler/class.optimized-inlined.wast
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
(module
|
||||||
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $v (func))
|
||||||
|
(memory $0 1)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $start (; 0 ;) (type $v)
|
||||||
|
(local $0 i32)
|
||||||
|
(local $1 i32)
|
||||||
|
(local $2 f32)
|
||||||
|
(local $3 f32)
|
||||||
|
(drop
|
||||||
|
(block (result i32)
|
||||||
|
(block $__inlined_func$class/Animal.add (result i32)
|
||||||
|
(set_local $0
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(set_local $1
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(i32.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result f32)
|
||||||
|
(block $__inlined_func$class/Animal.sub<f32> (result f32)
|
||||||
|
(set_local $2
|
||||||
|
(f32.const 1)
|
||||||
|
)
|
||||||
|
(set_local $3
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
(f32.sub
|
||||||
|
(get_local $2)
|
||||||
|
(get_local $3)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
34
tests/compiler/class.optimized.wast
Normal file
34
tests/compiler/class.optimized.wast
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
(module
|
||||||
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $v (func))
|
||||||
|
(memory $0 1)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $class/Animal.add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
|
(i32.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $class/Animal.sub<f32> (; 1 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
||||||
|
(f32.sub
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 2 ;) (type $v)
|
||||||
|
(drop
|
||||||
|
(call $class/Animal.add
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $class/Animal.sub<f32>
|
||||||
|
(f32.const 1)
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
9
tests/compiler/class.ts
Normal file
9
tests/compiler/class.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
class Animal {
|
||||||
|
static MAX: i32 = 1;
|
||||||
|
static add(a: i32, b: i32): i32 { return a + b; }
|
||||||
|
static sub<T>(a: T, b: T): T { return a - b; } // tsc does not allow this
|
||||||
|
}
|
||||||
|
|
||||||
|
Animal.MAX;
|
||||||
|
Animal.add(1,2);
|
||||||
|
Animal.sub<f32>(1.0, 2.0);
|
80
tests/compiler/class.wast
Normal file
80
tests/compiler/class.wast
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
(module
|
||||||
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $v (func))
|
||||||
|
(global $class/Animal.MAX (mut i32) (i32.const 1))
|
||||||
|
(global $HEAP_START i32 (i32.const 4))
|
||||||
|
(memory $0 1)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $class/Animal.add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
|
(return
|
||||||
|
(i32.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $class/Animal.sub<f32> (; 1 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
||||||
|
(return
|
||||||
|
(f32.sub
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 2 ;) (type $v)
|
||||||
|
(drop
|
||||||
|
(get_global $class/Animal.MAX)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $class/Animal.add
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $class/Animal.sub<f32>
|
||||||
|
(f32.const 1)
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(;
|
||||||
|
[program.elements]
|
||||||
|
clz
|
||||||
|
ctz
|
||||||
|
popcnt
|
||||||
|
rotl
|
||||||
|
rotr
|
||||||
|
abs
|
||||||
|
ceil
|
||||||
|
copysign
|
||||||
|
floor
|
||||||
|
max
|
||||||
|
min
|
||||||
|
nearest
|
||||||
|
sqrt
|
||||||
|
trunc
|
||||||
|
current_memory
|
||||||
|
grow_memory
|
||||||
|
unreachable
|
||||||
|
load
|
||||||
|
store
|
||||||
|
reinterpret
|
||||||
|
select
|
||||||
|
sizeof
|
||||||
|
changetype
|
||||||
|
isNaN
|
||||||
|
isFinite
|
||||||
|
assert
|
||||||
|
parseInt
|
||||||
|
parseFloat
|
||||||
|
class/Animal
|
||||||
|
class/Animal.MAX
|
||||||
|
class/Animal.add
|
||||||
|
class/Animal.sub
|
||||||
|
[program.exports]
|
||||||
|
|
||||||
|
;)
|
Loading…
x
Reference in New Issue
Block a user