mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 23:12:19 +00:00
Add 'instantiate<T>' builtin (like 'new' but from a type), see #349
This commit is contained in:
parent
1d93877e7c
commit
1149abf824
@ -2322,6 +2322,25 @@ export function compileCall(
|
|||||||
// thus must be used with care. it exists because it *might* be useful in specific scenarios.
|
// thus must be used with care. it exists because it *might* be useful in specific scenarios.
|
||||||
return module.createCallIndirect(arg0, operandExprs, typeName);
|
return module.createCallIndirect(arg0, operandExprs, typeName);
|
||||||
}
|
}
|
||||||
|
case "instantiate": {
|
||||||
|
if (!(typeArguments && typeArguments.length == 1)) {
|
||||||
|
if (typeArguments && typeArguments.length) compiler.currentType = typeArguments[0];
|
||||||
|
compiler.error(
|
||||||
|
DiagnosticCode.Expected_0_type_arguments_but_got_1,
|
||||||
|
reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"
|
||||||
|
);
|
||||||
|
return module.createUnreachable();
|
||||||
|
}
|
||||||
|
let classInstance = typeArguments[0].classReference;
|
||||||
|
if (!classInstance) {
|
||||||
|
compiler.error(
|
||||||
|
DiagnosticCode.Operation_not_supported,
|
||||||
|
reportNode.range
|
||||||
|
);
|
||||||
|
return module.createUnreachable();
|
||||||
|
}
|
||||||
|
return compiler.compileInstantiate(classInstance, operands, reportNode);
|
||||||
|
}
|
||||||
|
|
||||||
// user-defined diagnostic macros
|
// user-defined diagnostic macros
|
||||||
|
|
||||||
|
@ -6651,9 +6651,10 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!classInstance) return module.createUnreachable();
|
if (!classInstance) return module.createUnreachable();
|
||||||
|
return this.compileInstantiate(classInstance, expression.arguments, expression);
|
||||||
|
}
|
||||||
|
|
||||||
var expr: ExpressionRef;
|
compileInstantiate(classInstance: Class, argumentExpressions: Expression[], reportNode: Node): ExpressionRef {
|
||||||
|
|
||||||
// traverse to the top-most visible constructor
|
// traverse to the top-most visible constructor
|
||||||
var currentClassInstance: Class | null = classInstance;
|
var currentClassInstance: Class | null = classInstance;
|
||||||
var constructorInstance: Function | null = null;
|
var constructorInstance: Function | null = null;
|
||||||
@ -6663,14 +6664,21 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
} while (currentClassInstance = currentClassInstance.base);
|
} while (currentClassInstance = currentClassInstance.base);
|
||||||
|
|
||||||
// if a constructor is present, call it with a zero `this`
|
// if a constructor is present, call it with a zero `this`
|
||||||
|
var expr: ExpressionRef;
|
||||||
if (constructorInstance) {
|
if (constructorInstance) {
|
||||||
expr = this.compileCallDirect(constructorInstance, expression.arguments, expression,
|
expr = this.compileCallDirect(constructorInstance, argumentExpressions, reportNode,
|
||||||
options.usizeType.toNativeZero(module)
|
this.options.usizeType.toNativeZero(this.module)
|
||||||
);
|
);
|
||||||
|
|
||||||
// otherwise simply allocate a new instance and initialize its fields
|
// otherwise simply allocate a new instance and initialize its fields
|
||||||
} else {
|
} else {
|
||||||
expr = this.makeAllocate(classInstance, expression);
|
if (argumentExpressions.length) {
|
||||||
|
this.error(
|
||||||
|
DiagnosticCode.Expected_0_arguments_but_got_1,
|
||||||
|
reportNode.range, "0", argumentExpressions.length.toString(10)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expr = this.makeAllocate(classInstance, reportNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentType = classInstance.type;
|
this.currentType = classInstance.type;
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
@builtin export declare function assert<T>(isTrueish: T, message?: string): T;
|
@builtin export declare function assert<T>(isTrueish: T, message?: string): T;
|
||||||
@builtin export declare function unchecked<T>(expr: T): T;
|
@builtin export declare function unchecked<T>(expr: T): T;
|
||||||
@builtin export declare function call_indirect<T>(target: void, ...args: void[]): T;
|
@builtin export declare function call_indirect<T>(target: void, ...args: void[]): T;
|
||||||
|
@builtin export declare function instantiate<T>(...args: void[]): T;
|
||||||
|
|
||||||
@builtin export declare function i8(value: void): i8;
|
@builtin export declare function i8(value: void): i8;
|
||||||
export namespace i8 {
|
export namespace i8 {
|
||||||
|
2
std/assembly/index.d.ts
vendored
2
std/assembly/index.d.ts
vendored
@ -112,6 +112,8 @@ declare function changetype<T>(value: any): T;
|
|||||||
declare function unchecked<T>(value: T): T;
|
declare function unchecked<T>(value: T): T;
|
||||||
/** Emits a `call_indirect` instruction, calling the specified function in the function table by index with the specified arguments. Does result in a runtime error if the arguments do not match the called function. */
|
/** Emits a `call_indirect` instruction, calling the specified function in the function table by index with the specified arguments. Does result in a runtime error if the arguments do not match the called function. */
|
||||||
declare function call_indirect<T>(target: Function | u32, ...args: any[]): T;
|
declare function call_indirect<T>(target: Function | u32, ...args: any[]): T;
|
||||||
|
/** Instantiates a new instance of `T` using the specified constructor arguments. */
|
||||||
|
declare function instantiate<T>(...args: any[]): T;
|
||||||
/** Tests if a 32-bit or 64-bit float is `NaN`. */
|
/** Tests if a 32-bit or 64-bit float is `NaN`. */
|
||||||
declare function isNaN<T = f32 | f64>(value: T): bool;
|
declare function isNaN<T = f32 | f64>(value: T): bool;
|
||||||
/** Tests if a 32-bit or 64-bit float is finite, that is not `NaN` or +/-`Infinity`. */
|
/** Tests if a 32-bit or 64-bit float is finite, that is not `NaN` or +/-`Infinity`. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user