Hey, great work! Just a heads up about licensing. JavaScript code fragments that you use inside the compiler to produce the final output are technically part of the source code, and thus the output is also GPLv3 licensed as a derived work.
That's a known GPL quirk, and other GPL-licensed compilers like GCC use a separate variant of GPL to avoid that collision.
You can see how GNU Bison does it: https://git.savannah.gnu.org/cgit/bison.git/tree/src/parse-g... since they put fragments of Bison code to the final generate source file. That's exactly what Joy does to generate JavaScript, so you should put similar notice to the repository.
I command-F searched for GopherJS, looking for the obvious question -- how is this different? -- but found nothing besides crediting it as “inspiration”.
So, how is this different?
EDIT: asked in the Golang slack. Will update when I find out the answer.
> GopherJS emulates a 32-bit environment. This means that int, uint and uintptr have a precision of 32 bits. However, the explicit 64-bit integer types int64 and uint64 are supported. The GOARCH value of GopherJS is "js".
Joy doesn't seem to be:
> [Joy ships] a minimal runtime only when it's needed
> Most existing Go code does not yet compile to Javascript. This is because most of the standard library still needs to be translated to Javascript. This will be a focus of the 2.0 release. Signup for the mailing list to follow along with the progress.
This has some obvious consequences in how they differ. For example, if I look at [0][1], GopherJS results in a huge amount of code bloat because it includes a translation of the Go runtime. A basic example 33 LOC grows to 44 LOC on its own, but with the GopherJS environment that becomes:
> 1470 LOC and 45kb, uncompressed and unminified. The bulk of which is the builtin library.
It will only compile what it needs to. So if you declare types that are never used, they won't show up in the resulting code. This goes for core packages too. If I change that code so it requires "fmt", the result explodes to 12845 LOC and 624kb ("fmt" imports a LOT of stuff).
(In GopherJS' defense, minification slims it down to 21kb, and the example probably is missing a production code compiler flag)
The examples on the Joy webpage look a lot more minification-friendly and easier to integrate with other JavaScript.
GopherJS is _not_ an emulator. Saying that it emulates a 32-bit environment means that `int` (which is architecture-specific in Go) is 4 bytes (compared to 8-bytes on amd64), and means that int64 is supported and does what you expect.
As a counterexample -- it is not possible to have a 33 LOC example that uses goroutines to only expand to 44 LOC. GopherJS goes to extremes to make sure that your Go code works as expected in the browser.
My company has a few libraries (including a language parser/compiler) currently written in Go, and we have a need for the exact same functionality in the browser and in other places (e.g., Node.js apps). Rather than port everything to JS and have two codebases to maintain, we tried translating with GopherJS, which seemed promising at first. But the emitted code was enormous, and it pulled in parts of the standard library that couldn't be transpiled. (Our code had limited dependencies, but our main problem was the "fmt" package, which, if I remember correctly, is somewhat special and not something you can just omit.) In the end, it was too much work for a small company with our limited resources.
I'll be back on this thread tomorrow to answer any lingering questions. Feel free to open an issue on github with any additional questions or ping me at twitter.com/@mattmueller.
I'll be here to answer any questions you might have!