diff --git a/src/compiler.ts b/src/compiler.ts index 710b778736..c05660ca9b 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -6109,6 +6109,38 @@ export class Compiler extends DiagnosticEmitter { } break; } + + case ElementKind.IndexSignature: { + const functionExpr = expression.expression; + const type = this.resolver.getTypeOfElement(target); + assert(functionExpr.kind == NodeKind.ElementAccess); + + if (!type) { + this.error( + DiagnosticCode.Expression_cannot_be_represented_by_a_type, + functionExpr.range + ); + return module.unreachable(); + } + + if (!type.signatureReference) { + this.error( + DiagnosticCode.Type_0_has_no_call_signatures, + functionExpr.range, + type.toString() + ); + return module.unreachable(); + } + + signature = type.signatureReference; + functionArg = this.compileElementAccessExpression( + functionExpr, + contextualType, + Constraints.ConvImplicit + ); + break; + } + case ElementKind.Class: { let classInstance = target; let typeArguments = classInstance.getTypeArgumentsTo(this.program.functionPrototype); diff --git a/tests/compiler/std/array-access.debug.wat b/tests/compiler/std/array-access.debug.wat index c564b8b000..4e2912860a 100644 --- a/tests/compiler/std/array-access.debug.wat +++ b/tests/compiler/std/array-access.debug.wat @@ -10,6 +10,7 @@ (global $~lib/shared/runtime/Runtime.Minimal i32 (i32.const 1)) (global $~lib/shared/runtime/Runtime.Incremental i32 (i32.const 2)) (global $~lib/native/ASC_SHRINK_LEVEL i32 (i32.const 0)) + (global $~argumentsLength (mut i32) (i32.const 0)) (global $~lib/memory/__data_end i32 (i32.const 284)) (global $~lib/memory/__stack_pointer (mut i32) (i32.const 33052)) (global $~lib/memory/__heap_base i32 (i32.const 33052)) @@ -26,6 +27,7 @@ (export "stringArrayMethodCall" (func $export:std/array-access/stringArrayMethodCall)) (export "stringArrayArrayPropertyAccess" (func $export:std/array-access/stringArrayArrayPropertyAccess)) (export "stringArrayArrayMethodCall" (func $export:std/array-access/stringArrayArrayMethodCall)) + (export "functionArrayElementCall" (func $export:std/array-access/functionArrayElementCall)) (func $~lib/array/Array<~lib/array/Array>#get:length_ (type $i32_=>_i32) (param $this i32) (result i32) local.get $this i32.load $0 offset=12 @@ -249,6 +251,24 @@ local.get $this i32.load $0 offset=4 ) + (func $~lib/array/Array<%28i32%29=>i32>#get:length_ (type $i32_=>_i32) (param $this i32) (result i32) + local.get $this + i32.load $0 offset=12 + ) + (func $~lib/array/Array<%28i32%29=>i32>#get:dataStart (type $i32_=>_i32) (param $this i32) (result i32) + local.get $this + i32.load $0 offset=4 + ) + (func $std/array-access/functionArrayElementCall (type $i32_=>_i32) (param $a i32) (result i32) + i32.const 123 + i32.const 1 + global.set $~argumentsLength + local.get $a + i32.const 0 + call $~lib/array/Array<%28i32%29=>i32>#__get + i32.load $0 + call_indirect $0 (type $i32_=>_i32) + ) (func $~stack_check (type $none_=>_none) global.get $~lib/memory/__stack_pointer global.get $~lib/memory/__data_end @@ -592,6 +612,62 @@ global.set $~lib/memory/__stack_pointer local.get $3 ) + (func $~lib/array/Array<%28i32%29=>i32>#__get (type $i32_i32_=>_i32) (param $this i32) (param $index i32) (result i32) + (local $value i32) + (local $3 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store $0 + local.get $index + local.get $this + call $~lib/array/Array<%28i32%29=>i32>#get:length_ + i32.ge_u + if + i32.const 32 + i32.const 96 + i32.const 114 + i32.const 42 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.get $this + call $~lib/array/Array<%28i32%29=>i32>#get:dataStart + local.get $index + i32.const 2 + i32.shl + i32.add + i32.load $0 + local.tee $value + i32.store $0 + i32.const 1 + drop + i32.const 0 + i32.eqz + drop + local.get $value + i32.eqz + if + i32.const 144 + i32.const 96 + i32.const 118 + i32.const 40 + call $~lib/builtins/abort + unreachable + end + local.get $value + local.set $3 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $3 + ) (func $export:std/array-access/i32ArrayArrayElementAccess (type $i32_=>_i32) (param $0 i32) (result i32) (local $1 i32) global.get $~lib/memory/__stack_pointer @@ -687,4 +763,23 @@ global.set $~lib/memory/__stack_pointer local.get $1 ) + (func $export:std/array-access/functionArrayElementCall (type $i32_=>_i32) (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store $0 + local.get $0 + call $std/array-access/functionArrayElementCall + local.set $1 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $1 + ) ) diff --git a/tests/compiler/std/array-access.release.wat b/tests/compiler/std/array-access.release.wat index 864a44ce47..b13d3e74ac 100644 --- a/tests/compiler/std/array-access.release.wat +++ b/tests/compiler/std/array-access.release.wat @@ -13,12 +13,14 @@ (data (i32.const 1160) "\01\00\00\00^\00\00\00E\00l\00e\00m\00e\00n\00t\00 \00t\00y\00p\00e\00 \00m\00u\00s\00t\00 \00b\00e\00 \00n\00u\00l\00l\00a\00b\00l\00e\00 \00i\00f\00 \00a\00r\00r\00a\00y\00 \00i\00s\00 \00h\00o\00l\00e\00y") (data (i32.const 1276) "\1c") (data (i32.const 1288) "\01") + (table $0 1 1 funcref) (export "memory" (memory $0)) (export "i32ArrayArrayElementAccess" (func $export:std/array-access/i32ArrayArrayElementAccess)) (export "stringArrayPropertyAccess" (func $export:std/array-access/stringArrayPropertyAccess)) (export "stringArrayMethodCall" (func $export:std/array-access/stringArrayMethodCall)) (export "stringArrayArrayPropertyAccess" (func $export:std/array-access/stringArrayArrayPropertyAccess)) (export "stringArrayArrayMethodCall" (func $export:std/array-access/stringArrayArrayMethodCall)) + (export "functionArrayElementCall" (func $export:std/array-access/functionArrayElementCall)) (func $~lib/string/String#startsWith (type $i32_=>_i32) (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -489,4 +491,32 @@ call $~lib/builtins/abort unreachable ) + (func $export:std/array-access/functionArrayElementCall (type $i32_=>_i32) (param $0 i32) (result i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1308 + i32.lt_s + if + i32.const 34096 + i32.const 34144 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store $0 + i32.const 123 + local.get $0 + i32.const 0 + call $~lib/array/Array<~lib/array/Array>#__get + i32.load $0 + call_indirect $0 (type $i32_=>_i32) + drop + unreachable + ) ) diff --git a/tests/compiler/std/array-access.ts b/tests/compiler/std/array-access.ts index 944edf6740..d982ebcf78 100644 --- a/tests/compiler/std/array-access.ts +++ b/tests/compiler/std/array-access.ts @@ -17,3 +17,9 @@ export function stringArrayArrayPropertyAccess(a: string[][]): i32 { export function stringArrayArrayMethodCall(a: string[][]): i32 { return a[0][1].startsWith(""); } + +// FIXME: Parenthesizing types is not supported +type T = (x: i32) => i32 +export function functionArrayElementCall(a: T[]): i32 { + return a[0](123); +} \ No newline at end of file