Skip to content

Implicitly resolve to callables when resolving call expressions #1320

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

Merged
merged 1 commit into from
Jun 9, 2020
Merged
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
11 changes: 11 additions & 0 deletions src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2384,6 +2384,17 @@ export class Resolver extends DiagnosticEmitter {
if (!instance) return null;
return instance.signature.returnType;
}
case ElementKind.GLOBAL:
case ElementKind.LOCAL:
case ElementKind.FIELD: {
let varType = (<VariableLikeElement>target).type;
let varElement = this.getElementOfType(varType);
if (!varElement || varElement.kind != ElementKind.FUNCTION_TARGET) {
break;
}
target = varElement;
// fall-through
}
case ElementKind.FUNCTION_TARGET: {
return (<FunctionTarget>target).signature.returnType;
}
Expand Down
111 changes: 111 additions & 0 deletions tests/compiler/function-expression.optimized.wat
Original file line number Diff line number Diff line change
@@ -1,5 +1,116 @@
(module
(type $none_=>_i32 (func (result i32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(type $none_=>_none (func))
(type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32)))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 1024) ",\00\00\00\01\00\00\00\01\00\00\00,\00\00\00f\00u\00n\00c\00t\00i\00o\00n\00-\00e\00x\00p\00r\00e\00s\00s\00i\00o\00n\00.\00t\00s")
(table $0 18 funcref)
(elem (i32.const 1) $start:function-expression~anonymous|0 $start:function-expression~anonymous|0 $start:function-expression~someName $start:function-expression~anonymous|2 $start:function-expression~anonymous|3 $start:function-expression~anonymous|4 $start:function-expression~anonymous|5 $start:function-expression~anonymous|3 $start:function-expression~anonymous|4 $start:function-expression~anonymous|5 $start:function-expression~anonymous|2 $function-expression/testGlobal~anonymous|0~anonymous|0 $function-expression/testGlobal~anonymous|0 $function-expression/testGlobal~anonymous|0~anonymous|0 $function-expression/testLocal~anonymous|0 $function-expression/testGlobal~anonymous|0~anonymous|0 $function-expression/testField~anonymous|0)
(export "memory" (memory $0))
(start $~start)
(func $start:function-expression~anonymous|0 (param $0 i32) (result i32)
local.get $0
)
(func $start:function-expression~someName
nop
)
(func $start:function-expression~anonymous|2 (result i32)
i32.const 1
)
(func $start:function-expression~anonymous|3 (param $0 i32) (param $1 i32) (result i32)
local.get $0
local.get $1
i32.add
)
(func $start:function-expression~anonymous|4 (param $0 i32) (param $1 i32) (result i32)
local.get $0
)
(func $start:function-expression~anonymous|5 (param $0 i32) (param $1 i32) (result i32)
i32.const 42
)
(func $function-expression/testGlobal~anonymous|0~anonymous|0 (param $0 i32) (result i32)
local.get $0
i32.const 24
i32.add
)
(func $function-expression/testGlobal~anonymous|0 (result i32)
i32.const 12
)
(func $function-expression/testLocal~anonymous|0 (result i32)
i32.const 14
)
(func $function-expression/testField~anonymous|0 (result i32)
i32.const 16
)
(func $~start
(local $0 i32)
(local $1 i32)
i32.const 1120
memory.size
local.tee $1
i32.const 16
i32.shl
local.tee $0
i32.gt_u
if
local.get $1
i32.const 66655
local.get $0
i32.sub
i32.const -65536
i32.and
i32.const 16
i32.shr_u
local.tee $0
local.get $1
local.get $0
i32.gt_s
select
memory.grow
i32.const 0
i32.lt_s
if
local.get $0
memory.grow
i32.const 0
i32.lt_s
if
unreachable
end
end
end
i32.const 1088
i32.const 16
i32.store
i32.const 1092
i32.const 1
i32.store
i32.const 1096
i32.const 3
i32.store
i32.const 1100
i32.const 4
i32.store
i32.const 1104
i32.const 17
i32.store
i32.const 1
i32.const 1104
i32.load
call_indirect (type $none_=>_i32)
call_indirect (type $i32_=>_i32)
i32.const 25
i32.ne
if
i32.const 0
i32.const 1040
i32.const 82
i32.const 3
call $~lib/builtins/abort
unreachable
end
)
)
39 changes: 39 additions & 0 deletions tests/compiler/function-expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,42 @@ function testNullable(b: boolean): (() => i32) | null {
}
}
assert(testNullable(false) == null);

// see: https://github.com/AssemblyScript/assemblyscript/issues/1289

var globalFunc: () => (x: i32) => i32;
function testGlobal(): void {
globalFunc = (): (x:i32) => i32 => {
let myFunc = (x: i32): i32 => {
return 24 + x;
};
return myFunc;
};
assert(globalFunc()(1) == 25);
}
testGlobal();

function testLocal(): void {
let localFunc = (): (x:i32) => i32 => {
let myFunc = (x: i32): i32 => {
return 24 + x;
};
return myFunc;
};
assert(localFunc()(1) == 25);
}
testLocal();

class FieldClass {
constructor(public fieldFunc: () => (x: i32) => i32) {}
}
function testField(): void {
let fieldInst = new FieldClass((): (x:i32) => i32 => {
let myFunc = (x: i32): i32 => {
return 24 + x;
};
return myFunc;
});
assert(fieldInst.fieldFunc()(1) == 25);
}
testField();
Loading