ezrosent / frawk

an efficient awk-like language
Apache License 2.0
1.24k stars 34 forks source link

"Failure in runtime invalid format arg Null (this should have been caught earlier)" #97

Closed benhoyt closed 1 year ago

benhoyt commented 1 year ago

With the following program, I'm seeing the message "failure in runtime invalid format arg Null (this should have been caught earlier). Halting execution" from frawk:

$ cat localarr.awk 
BEGIN {
    f()
}

function f(depth, a, k) {
    ++n
    a[n] = 100-n
    if (depth < 3) {
        f(depth+1)
    }
    for (k in a) {
        printf "depth %d: k=%d v=%d\n", depth, k, a[k]
    }
}

And the output:

$ frawk -f localarr.awk
failure in runtime invalid format arg Null (this should have been caught earlier). Halting execution
depth 3: k=4 v=96
depth 2: k=3 v=97
depth 1: k=2 v=98
$ echo $?
1

However, under Gawk/mawk/onetrueawk/goawk, this program works fine, and prints the extra line of output:

$ gawk -f localarr.awk
depth 3: k=4 v=96
depth 2: k=3 v=97
depth 1: k=2 v=98
depth 0: k=1 v=99

Something to do with local arrays?

ezrosent commented 1 year ago

Thanks for the report! This isn't really about arrays, it's more about a hole in how frawk handles printing functions that type inference has inferred nothing about ("Null" values). The bug goes away if you do BEGIN { f(0); } for example.

The issue here is that frawk monomorphizes functions: in this case it creates two copies of f based on the initial call-site and the recursive call.

frawk isn't able to infer any type information about depth in the first call, other than the fact that it is a scalar (indeed, you could pass it the empty string and it would produce the same output), but the recursive call always gets called with an int (depth+1), so we only get an error with depth 0.

The easiest fix I found was just to support "null" as a valid format argument type. Added your repro as a test case. Thanks again!