valderman / haste-compiler

A GHC-based Haskell to JavaScript compiler
http://haste-lang.org
BSD 3-Clause "New" or "Revised" License
1.45k stars 109 forks source link

Closure Compiler Discarding stdlib Functions #280

Open klarh opened 9 years ago

klarh commented 9 years ago

If we consider the following brief example:

{-# LANGUAGE OverloadedStrings #-}               
import Haste.Foreign                             

listHead::[Int]->IO Int                          
listHead = ffi "(function(lst) {return lst[0];})"

x = [17, 23, 14::Int]                            

main = listHead x >>= print                      

Running hastec --onexec test-opt.hs && node test-opt.js works as we would expect, printing "17" to stdout. However, if we instead run hastec --onexec --opt-minify test-opt.hs && node test-opt.js, we get an error that lst2arr is undefined. I know that lst2arr is used to marshal a haskell list into a javascript array for the FFI call, and I see that its only appearance in the generated (non-stdlib.js) code is as a string argument to a function, so I can see why closure might not notice that it is actually a function. I don't know the details of the sorts of optimizations closure applies, but is there anything we can do to let it know that these are functions?

Also, this is with gentoo's closure-compiler-bin-20130411.

valderman commented 9 years ago

The proper solution would probably be to reorganize the JS parts a bit, essentially shoving everything into some var rts = {'lst2arr': function(...) {...}, 'arr2lst': ...}; object and just making Closure aware of that object. Should probably be done anyway for code hygiene reasons, but the performance impact should probably be investigated first.

Short-term, we can preserve function names by doing: window['fun'] = fun; for any function fun we want to be able to call by name.