Conversation
Polymorphic ModuleT type: when parsing foreign declarations we don't have access to their type, and thus we need a `ModuleT ()` type. The original `Module` type becomes an alias for `ModuleT Type`.
It is required when runnings `moduleToJs`.
* export list might contain foreign imports
|
This adds To generate javascript modules I use I run into problem when using |
|
The issue is that declarations are encoded using an object, and |
| bindToJSON (NonRec ann n e) = object [ runIdent n .= ( annToJSON ann, exprToJSON e ) ] | ||
| bindToJSON (Rec bs) = object $ map (\((ann, n), e) -> runIdent n .= ( annToJSON ann, exprToJSON e ) ) bs | ||
| bindToJSON (NonRec ann n e) = toJSON [(runIdent n, annToJSON ann, exprToJSON e)] | ||
| bindToJSON (Rec bs) = toJSON $ map (\((ann, n), e) -> (runIdent n, annToJSON ann, exprToJSON e)) bs |
There was a problem hiding this comment.
I don't understand why this needs to change. It's a recursive group, so the order should be unimportant.
There was a problem hiding this comment.
I just couldn't compile the Aff module. It contains a group of recursive binds with applicativeAff, nonCanceler and alwaysCanceler. When reading it using a hash map the order was changed to nonCanceler, alwaysCanceler followed by applicativeAff. ILooking at the compiled code one can see that here order is important:
var applicativeAff = new Control_Applicative.Applicative(function () {
return applyAff;
}, function (v) {
return $foreign._pure(nonCanceler, v);
});
var nonCanceler = Data_Function["const"](Control_Applicative.pure(applicativeAff)(false));
var alwaysCanceler = Data_Function["const"](Control_Applicative.pure(applicativeAff)(true));
When applicativeAff is at the end, executing this in node was failing with an error indicating that applicativeAff passed to Control_Applicative.pure(applicativeAff) in nonCanceler is undefined.
There was a problem hiding this comment.
So far I tested this on a purescript react isomorphic app. At the end I run purescript dce-ed code on node and in the browser.
pure dce with uglifyify produced 705kB while pulp build -O with uglifyify 685kB.
There is still room for improvement though. Now I am only removing top level declarations and not touching foreign modules at all.
It will contian code which is unrealated to CoreFn.
This is done in an unsafe way, that may produce foreign module that is missing some declarations (since it blindly removes export statements).
|
With webpack I could reduce the bundle down to 440kB and with a naive removing of exports from foreign modules additional 20kB - so I guess it makes sense to do that in a safer way. |
Perform dce in the foreign module: only on the export statements. This makes some assumptions and might fail if one using dynamic features of JavaScript, eval, etc. The `purs dce -O1` switch will enable this optimization. I am thinking about including `-O2` which would do dce on all declarations of the foreign module rather than just on exports. Right now any non export declaration that is referenced (as `exports.ident` or `export["ident"]`) in non export statements is included.
|
Thanks for taking the time to work on this! This is obviously a very big change, and could eventually replace
Once it's thoroughly tested on lots of code (maybe after 1.0 even), we could deprecate What do you think? |
|
Also, now would be the time to break the corefn format, if we're going to do it, since we can do it in 0.12.0. |
|
I agree, that indeed needs some time to mature and grow its test suite and be tested on real projects. I will prepare PR for the json representation. |
|
I'll be glad to test it out, if any help is needed in that department 😃 |
|
@paf31 maybe when you will announcing the next version of purescript you could include a line about new experimental (external) tool for tree shaking? |
|
Here it is zephyr. |
Yes, I think we should definitely do that. Thanks! |
Can we do this? Corefn is kind of a pain to work with, enough so that I've given up on writing a JSONSchema for it. It being a pain to work with is a sentiment shared by others that aren't known/active in the PS community. |
|
Yes. If you have experience working with it, it would be good to get suggestions for a better format. |
|
Here are some things we found hard, in no particular order: Very few things are named.It can be kind of hard to know which parts are which when you're deep in the nesting. It required me to explain what each piece of the JSON was in order for others to understand what they were looking at. [
"Case",
[
[
"Var",
"v"
]
],
[
[
[
[
"LiteralBinder",
[
"IntLiteral",
1
]
]
],
[
"Literal",
[
"IntLiteral",
1
]
]
],
[
[
"NullBinder"
],
[
"Literal",
[
"IntLiteral",
0
]
]
]
]
]The S-expression encoding feels harder to work with than an object encoding would.This ties in with the naming concern. I see the appeal for the S-expression encoding, but I think it would be better if we just had a way to dump an actual S-expression and left the JSON dump as an object. [
"Abs",
"dict",
[
"Accessor",
"foo",
[
"Var",
"dict"
]
]
]vs {
"type": "Abs",
"argument": "dict",
"body": {
"type": "Accessor",
"key": "foo",
"object": {
"type": "Var",
"name": "dict"
}
}
}I have no strong feelings on what the names should be, but they should exist. The value of each
|
|
I agree with @joneshf, having more verbose output would make it much easier to work with the json files. |
|
@joneshf Thank you for the detailed notes! I can't disagree with anything you've said. The S-expression syntax was something of an experiment to begin with, and maybe it hasn't worked out. I would be fine with breaking the format to use the suggested @rightfold Any thoughts? |
|
I agree. Especially problems with ambiguous names |
|
I think we should also change |
Attempt to solve #2970