Hacker News new | past | comments | ask | show | jobs | submit login
RubyFlux: a Ruby to Java compiler (github.com/headius)
112 points by neXter on Dec 28, 2012 | hide | past | favorite | 39 comments



Quick, someone needs to complete the circle!

Compile your ruby code to java with this new compiler.

Then compile your java code to javascript with GWT https://developers.google.com/web-toolkit/

Then run your javascript inside ruby with ExecJS https://gist.github.com/4106776

Bonus points if you can make your original ruby code interact with the javascript in the ruby VM.


Are there any production-quality cross-language compilers that support all the subtle semantics of the source language correctly? (I'm excluding C as a target language, which I know is often used as an output format for production-quality compilers).

I feel like I always see projects like this that have just started out, and provide no discussion of the difficult edge cases and how they will be supported. Correctly implementing a programming language is a really hard problem. Programming languages have tons and tons of subtle edge cases, like what happens if you add two objects of different types (think about the "wat?" talk: http://www.youtube.com/watch?v=kXEgk1Hdze0). If you don't get all these semantics correct, then your implementation won't be compatible with code written on other implementations.

Charles Nutter has obviously done a lot of work implementing Ruby in the past so is surely aware of all of this. I just wonder, when I see a project like this, what the ultimate plan is. Is it:

- the project is new and incomplete, but we plan to work on it until it correctly supports all semantics of the source language, even if the generated code gets uglier and more complicated as a result

- the project is new and incomplete, and we'll add support for more stuff but not get too worried about every last quirk of the source language, especially if it makes the generated code get too complicated

- the project is just an interesting hack, a fun side project, an experimental prototype or proof-of-concept, etc, and you shouldn't expect much compatibility.


I would say it is the second goal right now. Implementing JRuby and Mirah taught me a lot about features of Ruby that can map directly to Java/JVM, and I feel like this can be a very useful, functional subset of Ruby. Because this is a "compile the world" approach, things like evaluation probably will never be supported. But because it can generate the whole system, things like methods_missing, send, and respond_to? are all doable (and I just pushed m_m support a few hours ago). That opens up possibilities that are hard to achieve in typical statically typed languages without requiring any complicated dynamic dispatch system.

Honestly I feel like the biggest feature of both Mirah and RubyFlux are their ability to produce binaries that have no external dependencies. You only pay for what you use, and in both cases you,really just doing normal JVM calls under the covers. What Mirah achieves through static typing, RubyFlux achieves by generating all method names as stubs on a base class.

As others have pointed out...it is also just a fun experiment :-) But that is how both JRuby and Mirah started out too.


Could someone explain why this is needed?

I don't understand why someone wouldn't just write Java if they wanted to write Java.

I also don't understand why anyone would want generated code. The unnecessary abstraction leaves you less expressive and with less control.

Not trying to be a troll here, just hoping to learn something I'm missing.


It may not be needed. The author may just have done it because they could, and thought it was neat.

But the potential reasons for wanting it is that now the runtime is the JVM, MRI (Matz's Ruby interpreter). JRuby accomplishes using the JVM as the runtime for Ruby by reimplementing the Ruby runtime in Java. This is a different approach, one in which Ruby code is compiled to Java code, rather than using Java runtime interpret Ruby code.


This could be useful for someone wanting to whip up some Android code in Ruby, but not wanting to import the full JRuby or Ruby NDK overhead.

I bet it's mostly for fun. He essentially extracted his JRuby JIT into a conventional compiler.

In other words, a neat hack.


All the more so because current "jruby-on-Android" has performance problems. This hits particularly hard on startup (where a simple app can take several seconds to get past a splash page; see http://ruboto-startup.heroku.com/measurements for timing). But even once the app gets running, things still drag compared to a conventional JVM because the JIT doesn't work (due to Android's nonstandard Dalvik bytecodes).

If rubyflux winds up bypassing most of this overhead, it could be a major win. (Right now, I've got a project to try to use Scala to try to build a full-featured, reduced-boilerplate Android environment here: http://rst.github.com/positronic_docs.html --- but I'd really rather be using Ruby if the performance penalties could be ironed out.)


Definitely with Android. Lots of people want to make Android apps, but a decent percentage do not want to use Java. I prefer Mono for Android as a native alternative, but this could be nice for those that want to use a more dynamic language than C# or F# (Mono for Android does not have real support for dynamic languages due to limitations imposed by the Dalvik VM).


Weirdly, I was wondering about the existence of something like this about 20 minutes ago. I'm using Grails for work, and it's pretty unpleasant. I don't want to write Groovy, but I have to write Groovy.


You're essentially asking why someone would write a compiler. Why wouldn't someone consume target language X directly instead of using a compiler to generate output in target language X. We want our programs to wind up as machine language, so why not write opcodes for the host ISA instead of writing in, say, any other language?


there are a lot of people who want to have java written, but don't want to write java. this way you might get less control, but you get the greater expressiveness of ruby.


This is great, it's nice to see people pushing the boundaries, shaking bottles and trying to get out of the "same ol' same ol'" frame of mind from time to time.

Looking forward to more.


Cross-language compilers aren't a particularly new concept, though. And I fail to see how this one's exactly useful, either. Seems more like an "it can be done" sort of challenge, rather than a tool people would use in everyday programming.

But since it's currently the #1 post on Hacker News, maybe people do have some use for a Ruby-to-Java compiler, so could you enlighten me?


See http://stackoverflow.com/questions/12487986/how-can-i-make-r... . The tl;dr of it is that MRI is atrocious at memory management. For political reasons we are stuck using Ruby in a situation like that; if we could easily, accurately compile that to Java and run it with with java -jar my_script.jar it'd be awesome.


You are aware of JRuby, no?


And just for anyone unaware, this project is by the author of JRuby.


Just for the sake of correctness, Charles Oliver Nutter is actually of one of the main developers of JRuby, a project created about 10 years ago but which has evolved a LOT since then. See http://en.wikipedia.org/wiki/JRuby#History


I am aware, but I haven't really had the time to get involved in testing it. I know we'd have to make some code changes because we depend on modules with native extensions in our script, but I don't know that they'd really be prohibitive.

Much easier would be: "Make this Java with one command to a cross-compiler".


Thanks, I figured there would be some situation like this that'd inspire one to write a cross compiler.


Think of this as art - it doesn't need to have a purpose.

Or think of it as the solution to a problem yet to be discovered - isn't that how most discoveries are made?

Either way great achievement.


It is a feat of compiler design if it works even adequately. I was expecting to see some example output, though.


I'll try to add some for you tonight :-)


Cross-language compilers are not a new concept, you're right about that. I was more enthusiastic about the fact that any person trying to offer alternatives is doing a good deed.

Whether or not this has practical applications is irrelevant for now, the project seems to be in its infancy. Nonetheless, it's a good thing that the author is trying and tackling new concepts.


Sweet! Another neat project from Mr. Charles Nutter. I look forward to experimenting with this. One of my latest projects involves a cross-platform GUI built with the help of JRuby.


Mirah is a very similar project. It's a language that's very similar to Ruby that compiles directly onto the JVM with no runtime. It's also by Charles Nutter.


The difference between this and Mirah is that Mirah is more just a (beautiful) Java front-end: it looks like Ruby, but with just enough annotations to allow for strongly typed output. This looks a a bit more loose than that.


Not actually a compiler, more of a translator.


You're correct; however, unfortunately most discussions on here ignore the difference, I've noticed.


What is the difference? As far as I know any program that translates code from one language to another is a compiler.


you are correct sir, the term generally used is source to source compiler.


aka transpiler


> As far as I know any program that translates code from one language to another is a compiler.

No, there's a distinction between a code translation and a code compilation. At an abstract level, it's the difference between an actual Turing machine encoded with a specific set of instructions, and a Universal Turing machine along with an encoded representation of a program. Logically equivalent, yes, but that's not the same thing as saying that they're actually the same thing. (If they were, this would mean that any Turing-complete languages would be the same, so you might as well just write COBOL!)

Compilation is not just a matter of "produce another piece of source code that appears to have the same logic when executed". With compilation, the only information required at runtime is the input to the program itself (which is never known at compiletime, unless your program is one massive thunk - which would be kind of a useless program!). When translating code to another language like, eg., Javascript, this isn't the case, because the input to the program isn't fed directly to the output of the translation; rather, both are fed to the interpreter which executes one on the other.

This applies whether the target language for the translation is itself an interpreted language or a compiled language, but in practice, the translated form of a compiled language (ie, C) can itself be compiled immediately as part of the translation, so this isn't really a relevant distinction there.

(By this logic, it would seem that javac is a translator, not a compiler, which is almost half-true, but only because Java itself blurs the distinction[1]. javac compiles Java code to run "natively" on the Java virtual machine, and that machine is virtualized on actual hardware. So no input is required at runtime from the perspective of someone inside the virtual machine; however, since we're outside that hypothetical bubble, we can't actually execute that code natively and need to run a second translation at runtime - ie, the "just-in-time" portion of the process).

The reason this distinction is important has to do with the portability, reliability, and predictability of the generated code. Compiled code is inherently less portable (or at least, no more portable) than the pre-compilation source (whatever that language is). This is why languages like C are compiled for a particular system. On the other hand, the compiled form "solves" a lot of the decision problems that don't require executing (or even knowing) the input before-the-fact.

An interesting example of this problem is hiphop-php. As one of the other commenters pointed out, when translating code from one language to another, you have to encompass all of the quirks of the language (like 'wat') properly. The hiphop-php output is incredibly large because it has to statically determine the actions required when, ie, two variables are added, but one is a number and one is a string. This is just a feature of a dynamically typed language, yes, but it's not an issue if you simply wanted to translate Ruby to PHP, because you don't have to factor in any of that logic at compilation time - rather, it gets factored out and passed on to the interpreter. To create a truly self-executing, compiled form, that requires solving a lot of this logic insofar as your target system will allow, which is a much trickier process - you can't just rely on the runtime or the interpreter to pick up the slack for you.

[1] Incidentally, this was one of Java's selling points back in the day - hard to believe now!


"No, there's a distinction between a code translation and a code compilation." [citation needed]


According to wc -w, I wrote 571 words in support of that initial sentence. If you'd like citations for each of the individual points I use to illustrate my point, including the basic terminology, some cursory research should point you in the right direction of whatever you're looking for.

If you're looking for a tl;dr, you've come to the wrong place - not everything is so simple, and while I'm happy to explain my comments to people who ask politely (like isbadawi), I'm not really in the habit of writing MLA-style research papers on demand (and certainly not when the same information is already so widely and easily accessible).


> it's not an issue if you simply wanted to translate Ruby to PHP

This would be a broken transpiler. Headius factoring in all of that logic, just like hiphop-php.


You're right; I realized that afterwards but it's too late to change it. I was trying to think of a straightforward example of why this difference isn't just because of a difference in type systems, but that's hard, since types are so helpful in understanding the way languages work.

Or maybe I've just been thinking about types too much recently!


I'm getting a..

LoadError: no such file to load -- ruby_flux-1.0-SNAPSHOT


I didn't even get that far... I got 100 of these on the first step: error: cannot find symbol


I thought the whole fiscal cliff thing was quite nasty but this ...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: