haskell / play-haskell

Haskell Playground
129 stars 8 forks source link

Add javascript backend output support #31

Open jappeace opened 1 year ago

jappeace commented 1 year ago

Feature request

Recently I tried helping a someone on discord, however it's rather difficult to get a specific version of ghc compiler since I'm on nixos, I could only get ghc 9.7.1 but it didn't have the javascript backend. It'd be great if the playground would have the javascript backend supported as well so I can play around with FFI.

tomsmeding commented 1 year ago

What would you imagine the support to look like? Would the javascript be run in the client's browser, or on the server, and if the latter in what runtime? (Sorry, I'm not yet familiar with how the new backends work)

jappeace commented 1 year ago

I'd say add a js button next to asm for example:

image

I care not much for execution, I just want to see what it produces, to execute I can paste it into file to run in a browser.

tomsmeding commented 1 year ago

While this would be possible, I'm not sure it would be terribly useful. Following this page, I compiled the quicksort example to JS and looked at the outputs. We have:

And some other files, description copied from the link above (ghc wiki):

Amusingly, all.js.externs is identical to the output of the following bash script, both for a hello world example and for quicksort: echo '// GHCJS RTS externs for closure compiler ADVANCED_OPTIMIZATIONS'; echo; for i in $(seq 7 16384); do echo '/** @type {*} */'; echo "Object.d$i;"; done. Also it's 502KiB.

So what would you like to see? Putting all.js in a browser works, it seems, but it contains such a gigantic amount of cruft in addition to the code you're interested in that I'm not sure showing that in the playground output is helpful to anyone. To be noted is that the current output size limit is 100 000 bytes, whereas all.js is almost 23x that.

EDIT: all.js, out.js

jappeace commented 1 year ago

lol, yeah, that'd be the entire runtime ported to JS for us.

yeah, clearly I've not thought trough all implications of this request, but still having to build a custom ghc just to play around with javascript is kind of bad user experience.

Maybe it'd be possible to offer the files for download?

Kleidukos commented 1 year ago

Perhaps we can do some explicit post-processing like stripping the RTS stuff and piping through the Closure Compiler ? Yes it's not necessarily a faithful exact representation of what will be be output but:

  1. It's for an online visualisation, so it's okay to provide reduced outputs
  2. The playground is not an interactive development environment, we must give priority to ease of use.
tomsmeding commented 1 year ago

However, the closure compiler takes about 4.5 seconds to do so. And that's on a processor running at >5 GHz, which is more than your average VPS.

However, stripping RTS stuff is clearly something we can do -- if anything, we can transfer it to the client once instead of on every compile. But rts.js is just 282 KiB out of the full 2.2 MiB, so that doesn't help much.

@Kleidukos

It's for an online visualisation

Depends on what we want the goal of this to be. If the goal is what @jappeace said, which is to just offer the files for download: this would be possible, but it's only tangentially related to the goal of the playground, and we only sort-of by accident have some infrastructure for that. (Though not all.) So I'm not terribly enthousiastic about this, while I would be happy to give some tips/pointers on how to set up a very simple sandboxed compilation server.

If the goal is to run the code in the client's browser, we need all the code there, and it isn't very important how the code looks. But sending over multi-megabyte downloads for every run is a bit much -- and the closure compiler is apparently far too slow to be useful here.

If the goal is to let the user look at the code: closure compiler wouldn't help, and honestly I have no clue where to look even in the 1.7 MiB that is out.js, allegedly containing the user's haskell code. (It also includes compiled code from base, which perhaps is what makes it large.)

So I'm not terribly optimistic currently. :D But if your opinion differs on any of these points, please speak up! My opinions here are weakly held.

Kleidukos commented 1 year ago

For the JS dump (which is thankfully not the same as executing in the browser, which is fairly dangerous anyway), we have to find a way to isolate the user code, prettify it a bit and display it. Which means that we remove RTS, base and such.

If the goal is to run the code in the client's browser, we need all the code there, and it isn't very important how the code looks. But sending over multi-megabyte downloads for every run is a bit much -- and the closure compiler is apparently far too slow to be useful here.

In my professional opinion, this is not a thing we should aim to do.