mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-28 16:32:15 +00:00
Field initializers and constructors
This commit is contained in:
parent
b1e7b75ad7
commit
1b0ed61072
@ -2652,8 +2652,11 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
return this.module.createUnreachable();
|
return this.module.createUnreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compiles a call to a function. If an instance method, `this` is the first element in `argumentExpressions`. */
|
/**
|
||||||
compileCall(functionInstance: Function, argumentExpressions: Expression[], reportNode: Node): ExpressionRef {
|
* Compiles a call to a function. If an instance method, `this` is the first element in
|
||||||
|
* `argumentExpressions` or can be specified explicitly as the last argument.
|
||||||
|
*/
|
||||||
|
compileCall(functionInstance: Function, argumentExpressions: Expression[], reportNode: Node, thisArg: ExpressionRef = 0): ExpressionRef {
|
||||||
|
|
||||||
// validate and compile arguments
|
// validate and compile arguments
|
||||||
var parameters = functionInstance.parameters;
|
var parameters = functionInstance.parameters;
|
||||||
@ -2662,6 +2665,8 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var numParametersInclThis = functionInstance.instanceMethodOf != null ? numParameters + 1 : numParameters;
|
var numParametersInclThis = functionInstance.instanceMethodOf != null ? numParameters + 1 : numParameters;
|
||||||
var numArgumentsInclThis = argumentExpressions.length;
|
var numArgumentsInclThis = argumentExpressions.length;
|
||||||
var numArguments = functionInstance.instanceMethodOf != null ? numArgumentsInclThis - 1 : numArgumentsInclThis;
|
var numArguments = functionInstance.instanceMethodOf != null ? numArgumentsInclThis - 1 : numArgumentsInclThis;
|
||||||
|
if (thisArg)
|
||||||
|
numArgumentsInclThis++;
|
||||||
|
|
||||||
if (numArgumentsInclThis > numParametersInclThis) { // too many arguments
|
if (numArgumentsInclThis > numParametersInclThis) { // too many arguments
|
||||||
this.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range,
|
this.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range,
|
||||||
@ -2672,13 +2677,18 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
var operands = new Array<ExpressionRef>(numParametersInclThis);
|
var operands = new Array<ExpressionRef>(numParametersInclThis);
|
||||||
var operandIndex = 0;
|
var operandIndex = 0;
|
||||||
if (functionInstance.instanceMethodOf)
|
var argumentIndex = 0;
|
||||||
operands[operandIndex++] = this.compileExpression(argumentExpressions[0], functionInstance.instanceMethodOf.type);
|
if (functionInstance.instanceMethodOf) {
|
||||||
|
if (thisArg)
|
||||||
|
operands[operandIndex++] = thisArg;
|
||||||
|
else
|
||||||
|
operands[operandIndex++] = this.compileExpression(argumentExpressions[argumentIndex++], functionInstance.instanceMethodOf.type);
|
||||||
|
}
|
||||||
for (; operandIndex < numParametersInclThis; ++operandIndex) {
|
for (; operandIndex < numParametersInclThis; ++operandIndex) {
|
||||||
|
|
||||||
// argument has been provided
|
// argument has been provided
|
||||||
if (numArgumentsInclThis > operandIndex) {
|
if (numArgumentsInclThis > operandIndex) {
|
||||||
operands[operandIndex] = this.compileExpression(argumentExpressions[operandIndex], parameters[operandIndex + numParameters - numParametersInclThis].type);
|
operands[operandIndex] = this.compileExpression(argumentExpressions[argumentIndex++], parameters[operandIndex + numParameters - numParametersInclThis].type);
|
||||||
|
|
||||||
// argument has been omitted
|
// argument has been omitted
|
||||||
} else {
|
} else {
|
||||||
@ -2866,7 +2876,6 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// case LiteralKind.OBJECT:
|
// case LiteralKind.OBJECT:
|
||||||
// case LiteralKind.REGEXP:
|
// case LiteralKind.REGEXP:
|
||||||
// case LiteralKind.STRING:
|
|
||||||
}
|
}
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
@ -2901,9 +2910,46 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
var prototype = <ClassPrototype>resolved.element;
|
var prototype = <ClassPrototype>resolved.element;
|
||||||
var instance = prototype.resolveInclTypeArguments(expression.typeArguments, null, expression); // reports
|
var instance = prototype.resolveInclTypeArguments(expression.typeArguments, null, expression); // reports
|
||||||
if (instance) {
|
if (instance) {
|
||||||
// TODO: call constructor
|
var thisExpr = compileBuiltinAllocate(this, instance, expression);
|
||||||
|
var initializers = new Array<ExpressionRef>();
|
||||||
|
|
||||||
|
// use a temp local for 'this'
|
||||||
|
var tempLocal = this.currentFunction.getTempLocal(this.options.usizeType);
|
||||||
|
initializers.push(this.module.createSetLocal(tempLocal.index, thisExpr));
|
||||||
|
|
||||||
|
// apply field initializers
|
||||||
|
if (instance.members)
|
||||||
|
for (var member of instance.members.values()) {
|
||||||
|
if (member.kind == ElementKind.FIELD) {
|
||||||
|
var field = <Field>member;
|
||||||
|
var fieldDeclaration = field.prototype.declaration;
|
||||||
|
if (field.is(ElementFlags.CONSTANT)) {
|
||||||
|
assert(false); // there are no built-in fields currently
|
||||||
|
} else if (fieldDeclaration && fieldDeclaration.initializer) {
|
||||||
|
initializers.push(this.module.createStore(field.type.byteSize,
|
||||||
|
this.module.createGetLocal(tempLocal.index, this.options.nativeSizeType),
|
||||||
|
this.compileExpression(fieldDeclaration.initializer, field.type),
|
||||||
|
field.type.toNativeType(),
|
||||||
|
field.memoryOffset
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply constructor
|
||||||
|
var constructorInstance = instance.constructorInstance;
|
||||||
|
if (constructorInstance)
|
||||||
|
initializers.push(this.compileCall(constructorInstance, expression.arguments, expression,
|
||||||
|
this.module.createGetLocal(tempLocal.index, this.options.nativeSizeType)
|
||||||
|
));
|
||||||
|
|
||||||
|
// return 'this'
|
||||||
|
initializers.push(this.module.createGetLocal(tempLocal.index, this.options.nativeSizeType));
|
||||||
|
this.currentFunction.freeTempLocal(tempLocal);
|
||||||
|
thisExpr = this.module.createBlock(null, initializers, this.options.nativeSizeType);
|
||||||
|
|
||||||
this.currentType = instance.type;
|
this.currentType = instance.type;
|
||||||
return compileBuiltinAllocate(this, instance, expression);
|
return thisExpr;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
this.error(DiagnosticCode.Cannot_use_new_with_an_expression_whose_type_lacks_a_construct_signature, expression.expression.range);
|
this.error(DiagnosticCode.Cannot_use_new_with_an_expression_whose_type_lacks_a_construct_signature, expression.expression.range);
|
||||||
|
@ -436,13 +436,15 @@ export class Program extends DiagnosticEmitter {
|
|||||||
// if (classPrototype.isUnmanaged && instancePrototype.isAbstract) {
|
// if (classPrototype.isUnmanaged && instancePrototype.isAbstract) {
|
||||||
// this.error( Unmanaged classes cannot declare abstract methods. );
|
// this.error( Unmanaged classes cannot declare abstract methods. );
|
||||||
// }
|
// }
|
||||||
classPrototype.instanceMembers.set(name, prototype);
|
|
||||||
if (declaration.name.kind == NodeKind.CONSTRUCTOR) {
|
if (declaration.name.kind == NodeKind.CONSTRUCTOR) {
|
||||||
if (classPrototype.constructorPrototype)
|
if (classPrototype.constructorPrototype)
|
||||||
this.error(DiagnosticCode.Multiple_constructor_implementations_are_not_allowed, declaration.name.range);
|
this.error(DiagnosticCode.Multiple_constructor_implementations_are_not_allowed, declaration.name.range);
|
||||||
else
|
else {
|
||||||
|
prototype.set(ElementFlags.CONSTRUCTOR);
|
||||||
classPrototype.constructorPrototype = prototype;
|
classPrototype.constructorPrototype = prototype;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
classPrototype.instanceMembers.set(name, prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkOperators(declaration.decorators, prototype, classPrototype);
|
this.checkOperators(declaration.decorators, prototype, classPrototype);
|
||||||
@ -1075,7 +1077,6 @@ export class Program extends DiagnosticEmitter {
|
|||||||
case ElementKind.LOCAL:
|
case ElementKind.LOCAL:
|
||||||
case ElementKind.FIELD:
|
case ElementKind.FIELD:
|
||||||
if (!(targetType = (<VariableLikeElement>target).type).classType) {
|
if (!(targetType = (<VariableLikeElement>target).type).classType) {
|
||||||
console.log(propertyAccess.property.name + " on " + targetType);
|
|
||||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName, targetType.toString());
|
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName, targetType.toString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -1282,10 +1283,10 @@ export enum ElementFlags {
|
|||||||
PRIVATE = 1 << 15,
|
PRIVATE = 1 << 15,
|
||||||
/** Is an abstract member. */
|
/** Is an abstract member. */
|
||||||
ABSTRACT = 1 << 16,
|
ABSTRACT = 1 << 16,
|
||||||
|
/** Is a constructor. */
|
||||||
|
CONSTRUCTOR = 1 << 17,
|
||||||
/** Is an unmanaged class with limited capabilites. */
|
/** Is an unmanaged class with limited capabilites. */
|
||||||
UNMANAGED = 1 << 17,
|
UNMANAGED = 1 << 18,
|
||||||
/** Has already inherited base class static members. */
|
|
||||||
HAS_STATIC_BASE_MEMBERS = 1 << 18,
|
|
||||||
/** Is scoped. */
|
/** Is scoped. */
|
||||||
SCOPED = 1 << 19,
|
SCOPED = 1 << 19,
|
||||||
/** Is the start function. */
|
/** Is the start function. */
|
||||||
@ -1524,17 +1525,6 @@ export class FunctionPrototype extends Element {
|
|||||||
this.set(ElementFlags.INSTANCE);
|
this.set(ElementFlags.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether a getter function or not. */
|
|
||||||
get isGetter(): bool { return (this.flags & ElementFlags.GETTER) != 0; }
|
|
||||||
set isGetter(is: bool) { if (is) this.flags |= ElementFlags.GETTER; else this.flags &= ~ElementFlags.GETTER; }
|
|
||||||
|
|
||||||
/** Whether a setter function or not. */
|
|
||||||
get isSetter(): bool { return (this.flags & ElementFlags.SETTER) != 0; }
|
|
||||||
set isSetter(is: bool) { if (is) this.flags |= ElementFlags.SETTER; else this.flags &= ~ElementFlags.SETTER; }
|
|
||||||
|
|
||||||
// Whether a getter/setter function or not.
|
|
||||||
get isAccessor(): bool { return (this.flags & (ElementFlags.GETTER | ElementFlags.SETTER)) != 0; }
|
|
||||||
|
|
||||||
resolve(functionTypeArguments: Type[] | null = null, contextualTypeArguments: Map<string,Type> | null = null): Function | null {
|
resolve(functionTypeArguments: Type[] | null = null, contextualTypeArguments: Map<string,Type> | null = null): Function | null {
|
||||||
var instanceKey = functionTypeArguments ? typesToString(functionTypeArguments) : "";
|
var instanceKey = functionTypeArguments ? typesToString(functionTypeArguments) : "";
|
||||||
var instance = this.instances.get(instanceKey);
|
var instance = this.instances.get(instanceKey);
|
||||||
@ -1584,29 +1574,11 @@ export class FunctionPrototype extends Element {
|
|||||||
var parameterTypes = new Array<Type>(k);
|
var parameterTypes = new Array<Type>(k);
|
||||||
var typeNode: TypeNode | null;
|
var typeNode: TypeNode | null;
|
||||||
for (i = 0; i < k; ++i) {
|
for (i = 0; i < k; ++i) {
|
||||||
if (typeNode = declaration.parameters[i].type) {
|
typeNode = assert(declaration.parameters[i].type);
|
||||||
var parameterType = this.program.resolveType(typeNode, contextualTypeArguments, true); // reports
|
var parameterType = this.program.resolveType(typeNode, contextualTypeArguments, true); // reports
|
||||||
if (parameterType) {
|
if (parameterType) {
|
||||||
parameters[i] = new Parameter(declaration.parameters[i].name.name, parameterType, declaration.parameters[i].initializer);
|
parameters[i] = new Parameter(declaration.parameters[i].name.name, parameterType, declaration.parameters[i].initializer);
|
||||||
parameterTypes[i] = parameterType;
|
parameterTypes[i] = parameterType;
|
||||||
} else
|
|
||||||
return null;
|
|
||||||
} else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve return type
|
|
||||||
// TODO: 'this' type
|
|
||||||
var returnType: Type;
|
|
||||||
if (this.isSetter) {
|
|
||||||
returnType = Type.void; // not annotated
|
|
||||||
} else {
|
|
||||||
if (typeNode = declaration.returnType) {
|
|
||||||
var type = this.program.resolveType(<TypeNode>typeNode, contextualTypeArguments, true); // reports
|
|
||||||
if (type)
|
|
||||||
returnType = type;
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
} else
|
} else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -1620,6 +1592,21 @@ export class FunctionPrototype extends Element {
|
|||||||
if (!classInstance)
|
if (!classInstance)
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolve return type
|
||||||
|
// TODO: 'this' type
|
||||||
|
var returnType: Type;
|
||||||
|
if (this.is(ElementFlags.SETTER) || this.is(ElementFlags.CONSTRUCTOR)) {
|
||||||
|
returnType = Type.void; // not annotated
|
||||||
|
} else {
|
||||||
|
typeNode = assert(declaration.returnType);
|
||||||
|
var type = this.program.resolveType(<TypeNode>typeNode, contextualTypeArguments, true); // reports
|
||||||
|
if (type)
|
||||||
|
returnType = type;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
instance = new Function(this, internalName, functionTypeArguments, parameters, returnType, classInstance);
|
instance = new Function(this, internalName, functionTypeArguments, parameters, returnType, classInstance);
|
||||||
instance.contextualTypeArguments = contextualTypeArguments;
|
instance.contextualTypeArguments = contextualTypeArguments;
|
||||||
this.instances.set(instanceKey, instance);
|
this.instances.set(instanceKey, instance);
|
||||||
@ -1965,8 +1952,7 @@ export class ClassPrototype extends Element {
|
|||||||
this.program.error(DiagnosticCode.Structs_cannot_extend_classes_and_vice_versa, Range.join(declaration.name.range, declaration.extendsType.range));
|
this.program.error(DiagnosticCode.Structs_cannot_extend_classes_and_vice_versa, Range.join(declaration.name.range, declaration.extendsType.range));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
this.flags |= ElementFlags.HAS_STATIC_BASE_MEMBERS; // fwiw
|
|
||||||
|
|
||||||
// override call specific contextual type arguments if provided
|
// override call specific contextual type arguments if provided
|
||||||
var i: i32, k: i32;
|
var i: i32, k: i32;
|
||||||
@ -1996,6 +1982,13 @@ export class ClassPrototype extends Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.constructorPrototype) {
|
||||||
|
var partialConstructor = this.constructorPrototype.resolvePartial(typeArguments); // reports
|
||||||
|
if (partialConstructor)
|
||||||
|
instance.constructorInstance = partialConstructor.resolve(); // reports
|
||||||
|
// TODO: ^ doesn't know the return type, hence returns null
|
||||||
|
}
|
||||||
|
|
||||||
if (this.instanceMembers)
|
if (this.instanceMembers)
|
||||||
for (var member of this.instanceMembers.values()) {
|
for (var member of this.instanceMembers.values()) {
|
||||||
switch (member.kind) {
|
switch (member.kind) {
|
||||||
@ -2086,6 +2079,8 @@ export class Class extends Element {
|
|||||||
contextualTypeArguments: Map<string,Type> | null = null;
|
contextualTypeArguments: Map<string,Type> | null = null;
|
||||||
/** Current member memory offset. */
|
/** Current member memory offset. */
|
||||||
currentMemoryOffset: u32 = 0;
|
currentMemoryOffset: u32 = 0;
|
||||||
|
/** Constructor instance. */
|
||||||
|
constructorInstance: Function | null = null;
|
||||||
|
|
||||||
/** Constructs a new class. */
|
/** Constructs a new class. */
|
||||||
constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] | null = null, base: Class | null = null) {
|
constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] | null = null, base: Class | null = null) {
|
||||||
|
1
std/assembly.d.ts
vendored
1
std/assembly.d.ts
vendored
@ -237,6 +237,7 @@ declare class String {
|
|||||||
concat(other: string): string;
|
concat(other: string): string;
|
||||||
endsWith(other: string): bool;
|
endsWith(other: string): bool;
|
||||||
indexOf(other: string): u32;
|
indexOf(other: string): u32;
|
||||||
|
includes(other: string): bool;
|
||||||
startsWith(other: string): bool;
|
startsWith(other: string): bool;
|
||||||
substr(start: u32, length?: u32): string;
|
substr(start: u32, length?: u32): string;
|
||||||
substring(start: u32, end?: u32): string;
|
substring(start: u32, end?: u32): string;
|
||||||
|
1
std/portable.d.ts
vendored
1
std/portable.d.ts
vendored
@ -176,6 +176,7 @@ declare class String {
|
|||||||
readonly length: i32;
|
readonly length: i32;
|
||||||
private constructor();
|
private constructor();
|
||||||
indexOf(subject: string): i32;
|
indexOf(subject: string): i32;
|
||||||
|
includes(other: string): bool;
|
||||||
lastIndexOf(subject: string): i32;
|
lastIndexOf(subject: string): i32;
|
||||||
charAt(index: i32): string;
|
charAt(index: i32): string;
|
||||||
charCodeAt(index: i32): i32;
|
charCodeAt(index: i32): i32;
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
(module
|
|
||||||
(type $ii (func (param i32) (result i32)))
|
|
||||||
(type $v (func))
|
|
||||||
(import "env" "allocate_memory" (func $new/allocate_memory (param i32) (result i32)))
|
|
||||||
(memory $0 1)
|
|
||||||
(export "test" (func $new/test))
|
|
||||||
(export "memory" (memory $0))
|
|
||||||
(func $new/test (; 1 ;) (type $v)
|
|
||||||
(drop
|
|
||||||
(call $new/allocate_memory
|
|
||||||
(i32.const 4)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(drop
|
|
||||||
(call $new/allocate_memory
|
|
||||||
(i32.const 8)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
@ -1,15 +0,0 @@
|
|||||||
class Simple {
|
|
||||||
field: i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Generic<T> {
|
|
||||||
field: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
@global
|
|
||||||
declare function allocate_memory(size: usize): usize;
|
|
||||||
|
|
||||||
export function test(): void {
|
|
||||||
var simple = new Simple();
|
|
||||||
var generic = new Generic<f64>();
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
(module
|
|
||||||
(type $ii (func (param i32) (result i32)))
|
|
||||||
(type $v (func))
|
|
||||||
(import "env" "allocate_memory" (func $new/allocate_memory (param i32) (result i32)))
|
|
||||||
(global $HEAP_BASE i32 (i32.const 4))
|
|
||||||
(memory $0 1)
|
|
||||||
(export "test" (func $new/test))
|
|
||||||
(export "memory" (memory $0))
|
|
||||||
(func $new/test (; 1 ;) (type $v)
|
|
||||||
(local $0 i32)
|
|
||||||
(local $1 i32)
|
|
||||||
(set_local $0
|
|
||||||
(call $new/allocate_memory
|
|
||||||
(i32.const 4)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(set_local $1
|
|
||||||
(call $new/allocate_memory
|
|
||||||
(i32.const 8)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(;
|
|
||||||
[program.elements]
|
|
||||||
GLOBAL: NaN
|
|
||||||
GLOBAL: Infinity
|
|
||||||
FUNCTION_PROTOTYPE: isNaN
|
|
||||||
FUNCTION_PROTOTYPE: isFinite
|
|
||||||
FUNCTION_PROTOTYPE: clz
|
|
||||||
FUNCTION_PROTOTYPE: ctz
|
|
||||||
FUNCTION_PROTOTYPE: popcnt
|
|
||||||
FUNCTION_PROTOTYPE: rotl
|
|
||||||
FUNCTION_PROTOTYPE: rotr
|
|
||||||
FUNCTION_PROTOTYPE: abs
|
|
||||||
FUNCTION_PROTOTYPE: max
|
|
||||||
FUNCTION_PROTOTYPE: min
|
|
||||||
FUNCTION_PROTOTYPE: ceil
|
|
||||||
FUNCTION_PROTOTYPE: floor
|
|
||||||
FUNCTION_PROTOTYPE: copysign
|
|
||||||
FUNCTION_PROTOTYPE: nearest
|
|
||||||
FUNCTION_PROTOTYPE: reinterpret
|
|
||||||
FUNCTION_PROTOTYPE: sqrt
|
|
||||||
FUNCTION_PROTOTYPE: trunc
|
|
||||||
FUNCTION_PROTOTYPE: load
|
|
||||||
FUNCTION_PROTOTYPE: store
|
|
||||||
FUNCTION_PROTOTYPE: sizeof
|
|
||||||
FUNCTION_PROTOTYPE: select
|
|
||||||
FUNCTION_PROTOTYPE: unreachable
|
|
||||||
FUNCTION_PROTOTYPE: current_memory
|
|
||||||
FUNCTION_PROTOTYPE: grow_memory
|
|
||||||
FUNCTION_PROTOTYPE: changetype
|
|
||||||
FUNCTION_PROTOTYPE: assert
|
|
||||||
FUNCTION_PROTOTYPE: i8
|
|
||||||
FUNCTION_PROTOTYPE: i16
|
|
||||||
FUNCTION_PROTOTYPE: i32
|
|
||||||
FUNCTION_PROTOTYPE: i64
|
|
||||||
FUNCTION_PROTOTYPE: u8
|
|
||||||
FUNCTION_PROTOTYPE: u16
|
|
||||||
FUNCTION_PROTOTYPE: u32
|
|
||||||
FUNCTION_PROTOTYPE: u64
|
|
||||||
FUNCTION_PROTOTYPE: bool
|
|
||||||
FUNCTION_PROTOTYPE: f32
|
|
||||||
FUNCTION_PROTOTYPE: f64
|
|
||||||
FUNCTION_PROTOTYPE: isize
|
|
||||||
FUNCTION_PROTOTYPE: usize
|
|
||||||
GLOBAL: HEAP_BASE
|
|
||||||
CLASS_PROTOTYPE: new/Simple
|
|
||||||
CLASS_PROTOTYPE: new/Generic
|
|
||||||
FUNCTION_PROTOTYPE: new/allocate_memory
|
|
||||||
FUNCTION_PROTOTYPE: allocate_memory
|
|
||||||
FUNCTION_PROTOTYPE: new/test
|
|
||||||
[program.exports]
|
|
||||||
FUNCTION_PROTOTYPE: allocate_memory
|
|
||||||
FUNCTION_PROTOTYPE: new/test
|
|
||||||
;)
|
|
138
tests/compiler/std/new.optimized.wast
Normal file
138
tests/compiler/std/new.optimized.wast
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
(module
|
||||||
|
(type $ii (func (param i32) (result i32)))
|
||||||
|
(type $v (func))
|
||||||
|
(global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0))
|
||||||
|
(global $std/new/aClass (mut i32) (i32.const 0))
|
||||||
|
(global $HEAP_BASE i32 (i32.const 4))
|
||||||
|
(memory $0 1)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $std:heap/allocate_memory (; 0 ;) (type $ii) (param $0 i32) (result i32)
|
||||||
|
(local $1 i32)
|
||||||
|
(local $2 i32)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(return
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(set_local $1
|
||||||
|
(current_memory)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.gt_u
|
||||||
|
(i32.add
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(i32.shl
|
||||||
|
(get_local $1)
|
||||||
|
(i32.const 16)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.lt_s
|
||||||
|
(grow_memory
|
||||||
|
(select
|
||||||
|
(tee_local $2
|
||||||
|
(i32.trunc_s/f64
|
||||||
|
(f64.ceil
|
||||||
|
(f64.div
|
||||||
|
(f64.convert_u/i32
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(f64.const 65536)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(tee_local $1
|
||||||
|
(i32.sub
|
||||||
|
(i32.mul
|
||||||
|
(get_local $1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.gt_s
|
||||||
|
(get_local $2)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(set_local $1
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(block (result i32)
|
||||||
|
(set_global $std:heap/HEAP_OFFSET
|
||||||
|
(i32.add
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.and
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
(i32.const 7)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(set_global $std:heap/HEAP_OFFSET
|
||||||
|
(i32.add
|
||||||
|
(i32.or
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
(i32.const 7)
|
||||||
|
)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
(func $start (; 1 ;) (type $v)
|
||||||
|
(local $0 i32)
|
||||||
|
(local $1 i32)
|
||||||
|
(set_global $std:heap/HEAP_OFFSET
|
||||||
|
(get_global $HEAP_BASE)
|
||||||
|
)
|
||||||
|
(set_global $std/new/aClass
|
||||||
|
(block (result i32)
|
||||||
|
(i32.store
|
||||||
|
(tee_local $0
|
||||||
|
(call $std:heap/allocate_memory
|
||||||
|
(i32.const 8)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(f32.store offset=4
|
||||||
|
(get_local $0)
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
(i32.store
|
||||||
|
(tee_local $1
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(i32.add
|
||||||
|
(i32.load
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(f32.store offset=4
|
||||||
|
(get_local $1)
|
||||||
|
(f32.const 3)
|
||||||
|
)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
11
tests/compiler/std/new.ts
Normal file
11
tests/compiler/std/new.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class AClass {
|
||||||
|
static aStaticField: i32 = 0;
|
||||||
|
aField: i32 = 1;
|
||||||
|
anotherField: f32 = 2;
|
||||||
|
constructor(value: f32) {
|
||||||
|
this.aField += 1;
|
||||||
|
this.anotherField = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var aClass = new AClass(3);
|
273
tests/compiler/std/new.wast
Normal file
273
tests/compiler/std/new.wast
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
(module
|
||||||
|
(type $i (func (result i32)))
|
||||||
|
(type $ii (func (param i32) (result i32)))
|
||||||
|
(type $ifv (func (param i32 f32)))
|
||||||
|
(type $v (func))
|
||||||
|
(global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0))
|
||||||
|
(global $std:heap/ALIGN_LOG2 i32 (i32.const 3))
|
||||||
|
(global $std:heap/ALIGN_SIZE i32 (i32.const 8))
|
||||||
|
(global $std:heap/ALIGN_MASK i32 (i32.const 7))
|
||||||
|
(global $std/new/aClass (mut i32) (i32.const 0))
|
||||||
|
(global $HEAP_BASE i32 (i32.const 4))
|
||||||
|
(memory $0 1)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $std:heap/allocate_memory (; 0 ;) (type $ii) (param $0 i32) (result i32)
|
||||||
|
(local $1 i32)
|
||||||
|
(local $2 i32)
|
||||||
|
(local $3 i32)
|
||||||
|
(local $4 i32)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(return
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(set_local $1
|
||||||
|
(current_memory)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.gt_u
|
||||||
|
(i32.add
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(i32.shl
|
||||||
|
(get_local $1)
|
||||||
|
(i32.const 16)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.lt_s
|
||||||
|
(grow_memory
|
||||||
|
(select
|
||||||
|
(tee_local $2
|
||||||
|
(i32.trunc_s/f64
|
||||||
|
(f64.ceil
|
||||||
|
(f64.div
|
||||||
|
(f64.convert_u/i32
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(f64.const 65536)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(tee_local $3
|
||||||
|
(i32.sub
|
||||||
|
(i32.mul
|
||||||
|
(get_local $1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.gt_s
|
||||||
|
(get_local $2)
|
||||||
|
(get_local $3)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(set_local $4
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
)
|
||||||
|
(if
|
||||||
|
(i32.and
|
||||||
|
(block (result i32)
|
||||||
|
(set_global $std:heap/HEAP_OFFSET
|
||||||
|
(i32.add
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
)
|
||||||
|
(i32.const 7)
|
||||||
|
)
|
||||||
|
(set_global $std:heap/HEAP_OFFSET
|
||||||
|
(i32.add
|
||||||
|
(i32.or
|
||||||
|
(get_global $std:heap/HEAP_OFFSET)
|
||||||
|
(i32.const 7)
|
||||||
|
)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(return
|
||||||
|
(get_local $4)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $std/new/AClass#constructor (; 1 ;) (type $ifv) (param $0 i32) (param $1 f32)
|
||||||
|
(i32.store
|
||||||
|
(get_local $0)
|
||||||
|
(i32.add
|
||||||
|
(i32.load
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(f32.store offset=4
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 2 ;) (type $v)
|
||||||
|
(local $0 i32)
|
||||||
|
(set_global $std:heap/HEAP_OFFSET
|
||||||
|
(get_global $HEAP_BASE)
|
||||||
|
)
|
||||||
|
(set_global $std/new/aClass
|
||||||
|
(block (result i32)
|
||||||
|
(set_local $0
|
||||||
|
(call $std:heap/allocate_memory
|
||||||
|
(i32.const 8)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(i32.store
|
||||||
|
(get_local $0)
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(f32.store offset=4
|
||||||
|
(get_local $0)
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
(call $std/new/AClass#constructor
|
||||||
|
(get_local $0)
|
||||||
|
(f32.const 3)
|
||||||
|
)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(;
|
||||||
|
[program.elements]
|
||||||
|
GLOBAL: NaN
|
||||||
|
GLOBAL: Infinity
|
||||||
|
FUNCTION_PROTOTYPE: isNaN
|
||||||
|
FUNCTION_PROTOTYPE: isFinite
|
||||||
|
FUNCTION_PROTOTYPE: clz
|
||||||
|
FUNCTION_PROTOTYPE: ctz
|
||||||
|
FUNCTION_PROTOTYPE: popcnt
|
||||||
|
FUNCTION_PROTOTYPE: rotl
|
||||||
|
FUNCTION_PROTOTYPE: rotr
|
||||||
|
FUNCTION_PROTOTYPE: abs
|
||||||
|
FUNCTION_PROTOTYPE: max
|
||||||
|
FUNCTION_PROTOTYPE: min
|
||||||
|
FUNCTION_PROTOTYPE: ceil
|
||||||
|
FUNCTION_PROTOTYPE: floor
|
||||||
|
FUNCTION_PROTOTYPE: copysign
|
||||||
|
FUNCTION_PROTOTYPE: nearest
|
||||||
|
FUNCTION_PROTOTYPE: reinterpret
|
||||||
|
FUNCTION_PROTOTYPE: sqrt
|
||||||
|
FUNCTION_PROTOTYPE: trunc
|
||||||
|
FUNCTION_PROTOTYPE: load
|
||||||
|
FUNCTION_PROTOTYPE: store
|
||||||
|
FUNCTION_PROTOTYPE: sizeof
|
||||||
|
FUNCTION_PROTOTYPE: select
|
||||||
|
FUNCTION_PROTOTYPE: unreachable
|
||||||
|
FUNCTION_PROTOTYPE: current_memory
|
||||||
|
FUNCTION_PROTOTYPE: grow_memory
|
||||||
|
FUNCTION_PROTOTYPE: changetype
|
||||||
|
FUNCTION_PROTOTYPE: assert
|
||||||
|
FUNCTION_PROTOTYPE: i8
|
||||||
|
FUNCTION_PROTOTYPE: i16
|
||||||
|
FUNCTION_PROTOTYPE: i32
|
||||||
|
FUNCTION_PROTOTYPE: i64
|
||||||
|
FUNCTION_PROTOTYPE: u8
|
||||||
|
FUNCTION_PROTOTYPE: u16
|
||||||
|
FUNCTION_PROTOTYPE: u32
|
||||||
|
FUNCTION_PROTOTYPE: u64
|
||||||
|
FUNCTION_PROTOTYPE: bool
|
||||||
|
FUNCTION_PROTOTYPE: f32
|
||||||
|
FUNCTION_PROTOTYPE: f64
|
||||||
|
FUNCTION_PROTOTYPE: isize
|
||||||
|
FUNCTION_PROTOTYPE: usize
|
||||||
|
GLOBAL: HEAP_BASE
|
||||||
|
CLASS_PROTOTYPE: std:array/Array
|
||||||
|
PROPERTY: std:array/Array#length
|
||||||
|
CLASS_PROTOTYPE: Array
|
||||||
|
CLASS_PROTOTYPE: std:array/CArray
|
||||||
|
CLASS_PROTOTYPE: CArray
|
||||||
|
CLASS_PROTOTYPE: std:error/Error
|
||||||
|
CLASS_PROTOTYPE: Error
|
||||||
|
CLASS_PROTOTYPE: std:error/RangeError
|
||||||
|
CLASS_PROTOTYPE: RangeError
|
||||||
|
GLOBAL: std:heap/ALIGN_LOG2
|
||||||
|
GLOBAL: std:heap/ALIGN_SIZE
|
||||||
|
GLOBAL: std:heap/ALIGN_MASK
|
||||||
|
GLOBAL: std:heap/HEAP_OFFSET
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/allocate_memory
|
||||||
|
FUNCTION_PROTOTYPE: allocate_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/free_memory
|
||||||
|
FUNCTION_PROTOTYPE: free_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/copy_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/move_memory
|
||||||
|
FUNCTION_PROTOTYPE: move_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/set_memory
|
||||||
|
FUNCTION_PROTOTYPE: set_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/compare_memory
|
||||||
|
FUNCTION_PROTOTYPE: compare_memory
|
||||||
|
CLASS_PROTOTYPE: std:map/Map
|
||||||
|
CLASS_PROTOTYPE: Map
|
||||||
|
CLASS_PROTOTYPE: std:regexp/RegExp
|
||||||
|
CLASS_PROTOTYPE: RegExp
|
||||||
|
CLASS_PROTOTYPE: std:set/Set
|
||||||
|
PROPERTY: std:set/Set#size
|
||||||
|
CLASS_PROTOTYPE: Set
|
||||||
|
GLOBAL: std:string/EMPTY
|
||||||
|
GLOBAL: std:string/HEAD
|
||||||
|
FUNCTION_PROTOTYPE: std:string/allocate
|
||||||
|
CLASS_PROTOTYPE: std:string/String
|
||||||
|
FUNCTION_PROTOTYPE: std:string/String.__concat
|
||||||
|
FUNCTION_PROTOTYPE: std:string/String.__eq
|
||||||
|
CLASS_PROTOTYPE: String
|
||||||
|
FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator
|
||||||
|
FUNCTION_PROTOTYPE: std:string/parseInt
|
||||||
|
FUNCTION_PROTOTYPE: parseInt
|
||||||
|
FUNCTION_PROTOTYPE: std:string/parseFloat
|
||||||
|
FUNCTION_PROTOTYPE: parseFloat
|
||||||
|
CLASS_PROTOTYPE: std/new/AClass
|
||||||
|
GLOBAL: std/new/AClass.aStaticField
|
||||||
|
GLOBAL: std/new/aClass
|
||||||
|
[program.exports]
|
||||||
|
CLASS_PROTOTYPE: std:array/Array
|
||||||
|
CLASS_PROTOTYPE: Array
|
||||||
|
CLASS_PROTOTYPE: std:array/CArray
|
||||||
|
CLASS_PROTOTYPE: CArray
|
||||||
|
CLASS_PROTOTYPE: std:error/Error
|
||||||
|
CLASS_PROTOTYPE: Error
|
||||||
|
CLASS_PROTOTYPE: std:error/RangeError
|
||||||
|
CLASS_PROTOTYPE: RangeError
|
||||||
|
FUNCTION_PROTOTYPE: allocate_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/allocate_memory
|
||||||
|
FUNCTION_PROTOTYPE: free_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/free_memory
|
||||||
|
FUNCTION_PROTOTYPE: move_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/move_memory
|
||||||
|
FUNCTION_PROTOTYPE: set_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/set_memory
|
||||||
|
FUNCTION_PROTOTYPE: compare_memory
|
||||||
|
FUNCTION_PROTOTYPE: std:heap/compare_memory
|
||||||
|
CLASS_PROTOTYPE: std:map/Map
|
||||||
|
CLASS_PROTOTYPE: Map
|
||||||
|
CLASS_PROTOTYPE: std:regexp/RegExp
|
||||||
|
CLASS_PROTOTYPE: RegExp
|
||||||
|
CLASS_PROTOTYPE: std:set/Set
|
||||||
|
CLASS_PROTOTYPE: Set
|
||||||
|
CLASS_PROTOTYPE: std:string/String
|
||||||
|
CLASS_PROTOTYPE: String
|
||||||
|
FUNCTION_PROTOTYPE: parseInt
|
||||||
|
FUNCTION_PROTOTYPE: std:string/parseInt
|
||||||
|
FUNCTION_PROTOTYPE: parseFloat
|
||||||
|
FUNCTION_PROTOTYPE: std:string/parseFloat
|
||||||
|
;)
|
Loading…
x
Reference in New Issue
Block a user