This is probably a bad idea, since it depends quite a bit on peculiarities of fay's generated code.
Note the following points:
- Regardless of the name of the compiled module, fay instantiates into the variable
main
. - Under node.js, the return value from
require
is the module'smodules.export
(which initially is the same object asexport
-- but it doesn't necessarily stay that way). - A variable can be used before its scoping is declared with
var
. The variable referenced is the same. Its cares nothing for its source ordering, and everything for what has happened at runtime. - Fay by default (i.e. without
--library
) can instantiate an object and executemain
.
Notably, this means that we can, within main
, modify module.exports
or exports
to export the fay code. Of course, we must use the ffi, but it's a rather simple affair; the following, compiled without --library
(which, yes, is mildly counterintuitive, and really does lend credence to the hypothesis that this is a nasty hack, doesn't it) work to some extent:
import FFI
main :: Fay ()
main = ffi "module.exports = main"
when require
'd from node, the returned object is something to the effect of
{ 'Main$main':
{ forced: true,
value: { value: [Circular] } },
_: [Function: Fay$$_],
'$': [Function: Fay$$$],
'$fayToJs': [Function: Fay$$fayToJs],
'$jsToFay': [Function: Fay$$jsToFay] }
With a working knowledge of Fay's internal representations, it is then possible (though perhaps too much effort) to write a javascript wrapper for all the thunk-forcing and such.
(We could do more -- in fact, with a bit more ffi work, we could write all the bindings as ffi code. It would be mildly silly, though.)