Skip to content

Allow functions to be called directly from element accesses #2530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
<ElementAccessExpression>functionExpr,
contextualType,
Constraints.ConvImplicit
);
break;
}

case ElementKind.Class: {
let classInstance = <Class>target;
let typeArguments = classInstance.getTypeArgumentsTo(this.program.functionPrototype);
Expand Down
95 changes: 95 additions & 0 deletions tests/compiler/std/array-access.debug.wat
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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<i32>>#get:length_ (type $i32_=>_i32) (param $this i32) (result i32)
local.get $this
i32.load $0 offset=12
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
)
)
30 changes: 30 additions & 0 deletions tests/compiler/std/array-access.release.wat
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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<i32>>#__get
i32.load $0
call_indirect $0 (type $i32_=>_i32)
drop
unreachable
)
)
6 changes: 6 additions & 0 deletions tests/compiler/std/array-access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}