Extraneous end causes silent failure


#1

I had a very odd problem in that my program stopped running, and by stopped running I mean that the very first println in the function did not execute. However poking around in the code revealed that it was only one function that was not executing.

After some amount of cut-paste i finally tracked the problem down to:

function main()
...
for i=1:n 
  ...
  end
end
...
end

main()

An extraneous end. I figured that was the problem but it took me a bit to track down.

Apparently the extra end causes everything after it to be ignored (?), but there is no compilation error. It seems like the compiler should report an “unmatched end”.

Is this worthy of a bug report ?


#2

I can’t reproduce, please make an MWE that shows the end being ignored. Eg

shell> cat /tmp/test.jl
function main(n)
    for i=1:n
        println(i)
    end
end
end

main(10)

julia> include("/tmp/test.jl")
ERROR: LoadError: syntax: unexpected "end"
Stacktrace:
 [1] include at ./boot.jl:317 [inlined]
 [2] include_relative(::Module, ::String) at ./loading.jl:1038
 [3] include(::Module, ::String) at ./sysimg.jl:29
 [4] include(::String) at ./client.jl:396
 [5] top-level scope at none:0
in expression starting at /tmp/test.jl:6

julia> VERSION
v"1.1.0-DEV.720"

#3

well that’s very odd. ok. I’ll work on the example. there’s quite a bit of code, so it will take me a bit to cut it down. The extraneous end is definitely causing the problem. it’s happened to me a couple of times.


#4

Where and how did you execute the code? Paste into the REPL, include the file in the REPL?


#5

Well, this is fascinating. Simply uncomment the exit() to see the behavior. With exit commented, i get the compiler error. With exit() in the code, nothing happens, i.e. no compiler error and “test” is not printed.

I’m executing the file via

julia test.jl

and I’m using v"1.0.0"

function main()
    println("test")

    for i=1:5
        println("i=",i)
        end
    end
    #exit()
end

main()

edit:
seems like what’s happening is
1 the next-to-last end closes the function.
2 exit() becomes a valid statement
3 the last end is ignored
4 the code runs and the exit() executes before main.


#6

I think it’s just your indentation hiding what’s going on. I’d indent as

function main()
    println("test")

    for i=1:5
        println("i=",i)
    end
end
#exit()
end

So if the exit() is not commented out, then the script first defines function main and then exits. Note you can write anything on an unreachable line after an exit:

println("beginning")
exit()
hahaha this isn't even valid Julia code!

will run just fine, printing beginning before exiting.

If the exit() is not commented out, then your script defines function main and then has an extraneous end, which is of course an error.


#7

oh good grief that’s embarrassing…
edit: ok. it’s still embarrassing, except, are you saying that the “exit()” is recognized by the compiler in some way ? in your example the compiler should absolutely be complaining about the last line. you seem to be saying that it sees the exit() and stops compiling which is not at all expected.


#8

The code is parsed and executed expression by expression.


#9

I don’t think it’s embarrassing at all—it makes sense but it’s still kind of surprising. I’m not sure if this is a bug or a feature…