vlang / v

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io
MIT License
35.79k stars 2.16k forks source link

compile error, passing function pointer #1805

Closed mvlootman closed 5 years ago

mvlootman commented 5 years ago

V version: 0.1.18 OS: MacOS

What did you do? passing a function pointer to another function.

fn f(){
        println('func f')
}

fn main(){
        call_func(f)    
}

fn call_func(fp fn()){
        call_sub_func(fp) // <-- passing function to other func fails: expected `{` but got (``
}

fn call_sub_func(fp fn() ){
        fp()
}

What did you expect to see? No compile errors

What did you see instead? 0 v 0x000000010be1f646 Parser_check + 294 1 v 0x000000010be2e661 Parser_fn_call_args + 33 2 v 0x000000010be48db4 Parser_var_expr + 436 3 v 0x000000010be2aa25 Parser_name_expr + 2069 4 v 0x000000010be519fd Parser_factor + 2029 5 v 0x000000010be5118a Parser_unary + 298 6 v 0x000000010be50d66 Parser_term + 38 7 v 0x000000010be2ca8d Parser_expression + 173 8 v 0x000000010be48348 Parser_bterm + 40 9 v 0x000000010be1ffd2 Parser_bool_expression + 34 10 v 0x000000010be2eefd Parser_fn_call_args + 2237 11 v 0x000000010be2e4dc Parser_fn_call + 2364 12 v 0x000000010be2bb33 Parser_name_expr + 6435 13 v 0x000000010be519fd Parser_factor + 2029 14 v 0x000000010be5118a Parser_unary + 298 15 v 0x000000010be50d66 Parser_term + 38 16 v 0x000000010be2ca8d Parser_expression + 173 17 v 0x000000010be48348 Parser_bterm + 40 18 v 0x000000010be1ffd2 Parser_bool_expression + 34 19 v 0x000000010be40b34 Parser_statement + 612 20 v 0x000000010be1f96c Parser_statements_no_rcbr + 252 21 v 0x000000010be27355 Parser_fn_decl + 10533 22 v 0x000000010be2124c Parser_parse + 2188 23 v 0x000000010be3583f V_compile + 2015 24 v 0x000000010be337d0 main + 3424 25 v 0x000000010be0bc34 start + 52 26 ??? 0x0000000000000003 0x0 + 3 check() next token = } /pass_funcPointer.v:11:1: expected ( but got )

teggotic commented 5 years ago

You have some errors in your code.

fn f(){
    println('func f')
}

fn main(){
    call_func(f)    
}

fn call_func(fp fn()string) { //here
    call_sub_func(fp) // <-- passing function to other func fails: expected `{` but got (``
}

fn call_sub_func(fp fn()string){
    fp()
} // and here
mvlootman commented 5 years ago

You're right, I am a idiot ☺

avitkauskas commented 5 years ago

No, you get the same error with the right sintax anyway :)

check()
next token = `}`
0   v                                   0x0000000102196646 Parser_check + 294
1   v                                   0x00000001021a5661 Parser_fn_call_args + 33
2   v                                   0x00000001021bfdb4 Parser_var_expr + 436
3   v                                   0x00000001021a1a25 Parser_name_expr + 2069
4   v                                   0x00000001021c89fd Parser_factor + 2029
5   v                                   0x00000001021c818a Parser_unary + 298
6   v                                   0x00000001021c7d66 Parser_term + 38
7   v                                   0x00000001021a3a8d Parser_expression + 173
8   v                                   0x00000001021bf348 Parser_bterm + 40
9   v                                   0x0000000102196fd2 Parser_bool_expression + 34
10  v                                   0x00000001021a5efd Parser_fn_call_args + 2237
11  v                                   0x00000001021a54dc Parser_fn_call + 2364
12  v                                   0x00000001021a2b33 Parser_name_expr + 6435
13  v                                   0x00000001021c89fd Parser_factor + 2029
14  v                                   0x00000001021c818a Parser_unary + 298
15  v                                   0x00000001021c7d66 Parser_term + 38
16  v                                   0x00000001021a3a8d Parser_expression + 173
17  v                                   0x00000001021bf348 Parser_bterm + 40
18  v                                   0x0000000102196fd2 Parser_bool_expression + 34
19  v                                   0x00000001021b7b34 Parser_statement + 612
20  v                                   0x000000010219696c Parser_statements_no_rcbr + 252
21  v                                   0x000000010219e355 Parser_fn_decl + 10533
22  v                                   0x000000010219824c Parser_parse + 2188
23  v                                   0x00000001021ac83f V_compile + 2015
24  v                                   0x00000001021aa7d0 main + 3424
25  v                                   0x0000000102182c34 start + 52
/Users/alvis/Programming/v-code/test.v:11:1: expected `(` but got `)`
mvlootman commented 5 years ago

I ran into the issue in a bigger program, so I created this minimal example. Currently away from keyboard, I'll try again in about 6 hours.

teggotic commented 5 years ago

This is still a bug. Ill reopen

teggotic commented 5 years ago

The problem is that we are seeing variable, without checking if it's a function => we are not expecting it to be called. Fixing is not that easy though. We need to handle not only the function check itself, but functions with receivers. Or reimplement it completely in such a way so everything can be called and check if it can be called.

mvlootman commented 5 years ago

Updated the sample code (it contained syntax errors and the function pointer should be a function receiving no input and having no return values).

mvlootman commented 5 years ago

The problem is that we are seeing variable, without checking if it's a function => we are not expecting it to be called. Fixing is not that easy though. We need to handle not only the function check itself, but functions with receivers. Or reimplement it completely in such a way so everything can be called and check if it can be called.

The high order function doc ( https://vlang.io/docs#highfns ) does allow calling the variable.

fn run(value int, op fn(int) int) int {
        return op(value)
}

Isn't this the same, only with a deeper nesting? Or isn't it allowed to escape the function?

teggotic commented 5 years ago

I think it's just not implemented yet. You can't call a variable now, because there aren't any check if your variable is a function.

teggotic commented 5 years ago

You can't even use it without nesting.

The problem is that we are seeing variable, without checking if it's a function => we are not expecting it to be called. Fixing is not that easy though. We need to handle not only the function check itself, but functions with receivers. Or reimplement it completely in such a way so everything can be called and check if it can be called.

The high order function doc ( https://vlang.io/docs#highfns ) does allow calling the variable.

fn run(value int, op fn(int) int) int {
        return op(value)
}

Isn't this the same, only with a deeper nesting? Or isn't it allowed to escape the function?

mvlootman commented 5 years ago

I just tested the high order function example does work.

fn sqr(n int) int {
        return n * n
}

fn run(value int, op fn(int) int) int {
        return op(value)
}

fn main()  {
        println(run(5, sqr)) // "25"
}
teggotic commented 5 years ago

Oh, I'm sorry. But that's very strange. Ill recheck ASAP.

teggotic commented 5 years ago

The problem is that we are seeing variable, without checking if it's a function => we are not expecting it to be called. Fixing is not that easy though. We need to handle not only the function check itself, but functions with receivers. Or reimplement it completely in such a way so everything can be called and check if it can be called.

The high order function doc ( https://vlang.io/docs#highfns ) does allow calling the variable.

fn run(value int, op fn(int) int) int {
        return op(value)
}

Isn't this the same, only with a deeper nesting? Or isn't it allowed to escape the function?

You are right. The high order function doc ( https://vlang.io/docs#highfns ) does allow calling the variable. is working. As i understand now, it want you to call fp in call_func. But you are trying to just use it.

mvlootman commented 5 years ago

I am trying to write a benchmark module which should get passed a function to benchmark. The benchmark module would call a module method to execute the passed method. So I would need to pass the function on to another ( helper) method. That seems to fail.

teggotic commented 5 years ago

Found roots.

teggotic commented 5 years ago

I am trying to write a benchmark module which should get passed a function to benchmark. The benchmark module would call a module method to execute the passed method. So I would need to pass the function on to another ( helper) method. That seems to fail.

Could you load my branch and compile your code?

mvlootman commented 5 years ago

@Danil-Lapirow Just tested with the latest V with your merged PR. It works great, thank you!