quchen / stgi

A user-centric visual STG implementation to help understand GHC/Haskell's execution model.
Other
527 stars 26 forks source link

Why are missing free variables not detected at compile time? #89

Closed tomjaguarpaw closed 8 years ago

tomjaguarpaw commented 8 years ago

I tried the following program:

partialApply :: Program
partialApply = mconcat
    [ Stg.add
    , [program|
    main = \ => let one   = \ -> Int# 1#;
                    plus1 = \x -> add x one
                in plus1 one
    |]]

It compiled and ran, ending with

7. Errorenous state: one not in scope

I should have written

plus1 = \(one) x -> add x one

Why was this not detected at compile time?

tomjaguarpaw commented 8 years ago

Actually, plus1 = \(one) x -> add x one doesn't seem to fix it. Can you tell me what's wrong with this program?

tomjaguarpaw commented 8 years ago

I had to do

partialApply :: Program
partialApply = mconcat
    [ Stg.add
    , [program|
    main = \ => let one   = \ -> Int# 1#
                    in let plus1 = \(one) x -> add x one
                       in  plus1 one
    |]]

This seems to be a consequence of "Like letrec, but the bindings cannot refer to each other (or themselves). In other words, let is non-recursive." (from the README). But shouldn't this be enforced at compile time?

quchen commented 8 years ago

Why was this not detected at compile time?

For two reasons,

  1. STGi does not compile anything, it just takes the syntax tree as generated by the parser and puts it into the automaton
  2. The only static analysis that is done (right now) is by the parser, who catches some minor mistakes such as updatable closures that don’t make any sense, as noted in your other ticket #88.

As for how to write your program, I would use a letrec.

add = ... -- Prelude
main = \ => 
    letrec 
        one   = \ -> Int# 1#;
        plus1 = \(one) x -> add x one
    in plus1 one

I’ve tried building some better static analysis a couple of times, but it’s not as trivial as I initially thought. I have a long-standing ticket open for reporting unused globals, #23, and a branch that works on that issue (static-analysis it’s called I believe).

tomjaguarpaw commented 8 years ago

Thanks, I like your letrec version. Static analysis to detect these errors would be good and will have a look at your branch when I get the time.

quchen commented 8 years ago

Is there anything else I can help you with? Otherwise I’ll close the ticket.

tomjaguarpaw commented 8 years ago

That's fine. You can close this one if you like.