codeworld icon indicating copy to clipboard operation
codeworld copied to clipboard

Look into integrating reanimate

Open cdsmith opened this issue 4 years ago • 14 comments

The reanimate library is pretty exciting, and I'd love to provide an easier environment to experiment with it. Currently, it must be run as a binary, which either renders to a gif or similar format, or serves an interpreted file via HTTP. I want to look into whether it's easy to run reanimate via GHCJS and render into the local document, instead. If that were possible, I would add reanimate to the list of pre-installed dependencies for CodeWorld's native Haskell mode, so it could be used without locally installed tooling.

https://reanimate.github.io/

cdsmith avatar Jul 30 '20 14:07 cdsmith

@Lemmih in case you have thoughts.

cdsmith avatar Jul 30 '20 14:07 cdsmith

This would be great. Is it easy to compile Haskell libraries to Javascript? What are some common pitfalls?

lemmih avatar Jul 31 '20 01:07 lemmih

I guess the main open question is this: if you didn't have the filesystem or network at all, could I still use reanimate to build an animation, and then just ask it for the SVG at a given time? I can add SVG to an HTML document without too much difficulty (for example, the diagrams example at https://code.world/haskell#PfSPvyMNOP1r_mU0pY3wnZw -- there may be a better way to do it, but that one works)

Images are definitely a problem. Since you don't have access to the filesystem, you can't really load them that way. Any images would need to be referenced by URL instead of a file path.

I will start by trying to just build reanimate for GHCJS, and see if that succeeds.

cdsmith avatar Jul 31 '20 01:07 cdsmith

Okay, the first problem I ran into is that reanimate depends on chiphunk, which in turn depends on a C library. As long as that's the case, building with GHCJS won't be possible.

cdsmith avatar Jul 31 '20 02:07 cdsmith

I can move chuphunk to a separate package. I'm also using a C library for earclipping. Guess that'll have to be moved to a separate package as well. Then the core 'reanimate' library wouldn't use any C code.

Can I depend on 'hmatrix'? Does blas and lapack run as javascript? What about 'fsnotify'? Is it OK to depend on that library as long as it isn't actually used?

lemmih avatar Jul 31 '20 03:07 lemmih

hmatrix will not build with GHCJS. I know that one right off, because it's why I couldn't build the hamilton package. fsnotify is fine, as you say, so long as it isn't actually used.

cdsmith avatar Jul 31 '20 03:07 cdsmith

Ok, so 'chiphunk' and 'hmatrix' dependencies have to be moved to a separate package.

Is it possible to use Javascript libraries from Haskell? I'd like to use LaTeX.js and earcut.js

lemmih avatar Jul 31 '20 03:07 lemmih

Hm, maybe MathJax instead of LaTeX.js

lemmih avatar Jul 31 '20 03:07 lemmih

It's definitely possible to use GHCJS to build bindings for JavaScript libraries. I guess the completely self-contained way would be to (a) use the ghcjs-dom package to add a script element to the document, referencing the library on a CDN somewhere, (b) use an onload handler to wait for the script load to finish, and then (c) use JavaScriptFFI to call into the JavaScript library once it's loaded.

It sounds like this is becoming a pretty major change for reanimate. If you choose to do it, that's great, but it's way more than I expected.

cdsmith avatar Jul 31 '20 04:07 cdsmith

Is there an easy way of installing ghcjs and testing whether reanimate works with it? Looking at your install script, it seems fairly involved.

lemmih avatar Aug 01 '20 13:08 lemmih

Is there an easy way of installing ghcjs

That is the golden question, isn't it? I am not aware of an easy way of installing GHCJS. But assuming you have a relatively recent cabal and ghc installed, you can probably skip most of the steps from my install script, and do this:

  1. Clone GHCJS and change to that directory.
  2. ./utils/makePackages.sh
  3. cabal v2-install .
  4. ghcjs-boot

You may run into https://github.com/ghcjs/ghcjs/issues/740 and need to fix the symlink for ghcjs-boot. But maybe that bug is fixed in HEAD. I don't know. The install will likely take an hour or two.

cdsmith avatar Aug 01 '20 14:08 cdsmith

Sigh, I'm using double-conversion to pretty-print doubles and that library uses C. This is not gonna be easy.

lemmih avatar Aug 02 '20 08:08 lemmih

I couldn't figure out how to install GHCJS but I made Reanimate work with Asterius.

The reanimate-svg package still needs to know whether to use C code or if it should resort to a slower, pure-haskell implementation. Do you know if there's a way to detect if a package is being compiled by GHCJS?

lemmih avatar Aug 07 '20 09:08 lemmih

Okay, if it works with Asterius, then I think that's a good sign that GHCJS is likely to work, as well.

To detect if it's being compiled by GHCJS, you can do one of the following:

  1. In Cabal: if impl(ghcjs). See https://github.com/google/codeworld/blob/e2029cefde1a5982d60fb15ec25bf47264846bf6/codeworld-api/codeworld-api.cabal#L70 for an example.
  2. In Haskell with CPP: #ifdef ghcjs_HOST_OS. See https://github.com/google/codeworld/blob/e2029cefde1a5982d60fb15ec25bf47264846bf6/codeworld-api/src/CodeWorld/Driver.hs#L75 for an example.

cdsmith avatar Aug 07 '20 11:08 cdsmith