Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate modules in code generation #279

Closed
bergmark opened this issue May 3, 2013 · 7 comments
Closed

Separate modules in code generation #279

bergmark opened this issue May 3, 2013 · 7 comments

Comments

@bergmark
Copy link
Member

bergmark commented May 3, 2013

compileTopLevelModule should be less special, instead each module can generate all the code it needs and compileTopLevelModule can be responsible for the overall structure.
The generated modules can then look more like Haskell modules:

function Main ()
{
  var J = JQuery;
  var tail = Prelude.tail;
...
}
@tomlokhorst
Copy link

Somewhat related to this issue, it would be nice if the generated code uses the JavaScript module pattern.

Made up example:

module Test (hello) where

message :: String
message = "Hello, "

hello :: String -> String
hello s = message ++ s

Would generate this javascript:

var Test = Test || {};

(function (exports) {
  var message = "Hello, ";

  function hello(s) {
    return message + s;
  }

  exports.hello = hello;
})(Test);

This way, one can call hello from JavaScript like so:

Test.hello("you!");

@bergmark
Copy link
Member Author

I'm almost done with this now, it's on the modules branch: master...modules
Modules are generated like this:

var A = {}
var A.B = {};
var A.B.main = ...;
var A.B.someExportedImport = A.bar;

Internally Fay still uses qualified names for everything which makes the output a lot smaller.
I removed the distinction between compiling the toplevel module and others, and each module generates code independently (including transcoding). One issue remains: Haskell has a separate namespace for modules and constructors whereas JS doesn't; A.B could refer to both a module and a constructor. I might special case this when it happens so the constructor is used as the module, unless there's a better solution. It can lead to other problems, such as if the export is a read only property of functions: module A where data R = R module A.R where length = ... will break.

@tomlokhorst
Copy link

JavasScript is very dynamic, so it can handle using the same name for two different things :-)

You can extend existing objects if they already exist. For example:

// file A.js
A = A || {};
A.R = function A_R() { /* constructor */ };

// file A.R.js
A = A || {};
A.R = A.R || {};
A.R.length = function A_R_length() { /* some function */ }

Although I just realised that won't work if file A.R.js is loaded before A.js.
But you could probably do some prototype magic to make it work anyway.
Like any time you're setting something to a function, check if it already has properties, and reset those after setting the function.

@bergmark
Copy link
Member Author

Yeah, I keep track of which module paths have been added already, so I just need to add constructors to that list.
The length issue is this:

> var A = function () {};
undefined
> A.length = function () {};
[Function]
> A.length
0

@tomlokhorst
Copy link

length is a property on the function object, that's why that one doesn't work. It works for other property names.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length

There might be more Haskell names that conflict with JavaScript reserved words and such. I think in those cases you need to add something like a $ to "escape" those words, e.g A.$length$

@bergmark
Copy link
Member Author

Yes I'm aware :)

And yeah I'll probably $ them, doesn't matter for Fay internally, only for any JS code calling it.

@bergmark
Copy link
Member Author

This was released in 0.16.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants