-
Notifications
You must be signed in to change notification settings - Fork 89
Generated code
This is not completely up to date
This page explains what Fay outputs when you compile with it, and how you can configure it. I use a demo project with commandline examples throughout, so that you can reproduce the same inspection steps with your own project.
Fay outputs several components which may or may not be necessary depending on your use-case. In order of appearance:
- The module wrapper
- The runtime
- The actual code
- Exports
- Builtin-exports
- Instantiation of the module for executables
By default, Fay outputs a wrapper around all the code. So if we have a very simple module like this:
import Prelude
main = putStrLn "Hello, World!"
And we compile it with all the default options,
$ fay demo.hs
we get Main
as the default module wrapper:
$ head demo.js -n 1
var Main = function(){
If you want to disable the module wrapper all together, and output
code “naked”, you can use the --naked
flag:
$ fay demo.hs --naked
$ head demo.js -n 3
/*******************************************************************************
* Thunks.
*/
So it goes straight to outputting the runtime.
The “runtime” (that's a loose term) is a set of prim-ops and a couple thunk forcing operations that need to be implemented in JavaScript for speed reasons. It consists mainly of:
- The thunk code.
- The monad code.
- Prim-ops, so (*), (//), list producing operations, etc.
- FFI conversion functions.
You can read it in the file js/runtime.js in the fay repo.
You generally need all of this output, but simple primitive FFI conversions are specialised as specific functions, e.g.
$ grep '_int' demo.js | head -n 1
function Fay$$jsToFay_int(x){return x;}
So the more generic data type converter,
$ grep 'fayToJs(' demo.js | head -n 1
function Fay$$fayToJs(type,fayObj){
Could technically be ommitted. We'll see why this is useful to know later.
This section consists of a list of declarations for all the modules
being compiled into one big list. By default, output will be all on
one line, but you can use the -p
flag to make it prettier to read.
$ fay demo.hs --library --no-builtins -p
$ grep 'var Main$main' demo.js -A2
var Main$main = new Fay$$$(function(){
return Fay$$_(Prelude$putStrLn)(Fay$$list("Hello, World!"));
});
All modules symbols are named as ModuleName$theName
for namespacing.
Exports are things put in the module object, and they are controlled by your main module's export list, so:
$ fay demo.hs --library --no-builtins
$ grep '^// Exports' demo.js -A 1
// Exports
this.Main$main = Main$main;
So if you have a module like this:
module Exports where
import Prelude
main = putStrLn "Hello, World!"
foo = 123
Then you get main
and foo
exported:
$ fay exports.hs --library --no-builtins
$ grep '^// Exports' exports.js -A 2
// Exports
this.Exports$foo = Exports$foo;
this.Exports$main = Exports$main;
But if you just put (main)
in the exports list, you'll get just main:
$ fay exports.hs --library --no-builtins
$ grep '^// Exports' exports.js -A 2
// Exports
this.Exports$main = Exports$main;
This can be important to remember when considering compression.
Fay will export built-ins for use outside of Fay, such as:
- Thunk forcing.
- Thunk making.
- Conversions to and from JS.
So in here,
$ fay demo.hs --library
$ tail demo.js
// Exports
this.Main$main = Main$main;
// Built-ins
this._ = Fay$$_;
this.$ = Fay$$$;
this.$fayToJs = Fay$$fayToJs;
this.$jsToFay = Fay$$jsToFay;
};
we see some this.x = …
exports.
To stop the inessential ones from being exported, you can use the
--no-builtins
flag:
$ fay demo.hs --library --no-builtins
(Doesn't have to be combined with --library
, that's just for output
clarity in this demo.)
Leaving only the thunk forcer, which you will need to actually run your Fay code, so this can't be omitted:
$ tail demo.js -n 3
// Built-ins
this._ = Fay$$_;
};
By default we are compiling programs, so at the end of the file, we instantiate an instance of that module and run it:
$ tail demo.js -n 3
var main = new Main();
main._(main.Main$main);
As in GHC. If you want to disable this instantiation, you can use the
--library
flag:
$ fay demo.hs --library
$ tail demo.js -n 3
this.$jsToFay = Fay$$jsToFay;
};