If one were to开发者_开发知识库 implement Ruby on top of a Javascript engine (either in the browser or on top of standalone V8 or Spidermonkey), what would be the key impedance mismatches between the Ruby and JS object models ?
The most in-your-face one is obviously the fact that ECMAScript is prototype-based and Ruby is class-plus-mixin-based. Also, in Ruby, encapsulation is done with objects, in ECMAScript with closures.
However, my guess is that Ruby's control flow constructs are going to be a much bigger hurdle than its object model. After all, James Coglan's JS.Class is basically an implementation of Ruby's object model in ECMAScript and it's not that big.
ECMAScript simply lacks the tools needed to build your own control-flow constructs on top of it. Typically, you need either GOTO
, continuations or proper tail calls. If you have one of those, you can easily implement everything else: exceptions, loops, switches, threads, Fiber
s, generators, coroutines, … you name it.
But ECMAScript doesn't have them (and for good reason, at least in the case of GOTO
). The only control-flow construct ECMAScript has that is powerful enough to be able to build other constructs on top of is exceptions. Unfortunately, those are pretty slow. (Nonetheless, they have been used as an implementation substrate, for example in the Microsoft Live Labs Volta compiler, which used ECMAScript exceptions to implement .NET exceptions, iterators, generators and even threads.)
So, basically you are stuck with implementing at least your own call stack if not an entire interpreter (as is the case with HotRuby), performing global CPS transforms or something like that.
Basically, what you want from a Ruby engine running on top of ECMAScript, is
- a faithful implementation of the RubySpec (specifically the control-flow constructs such as threads, fibers,
throw
/catch
, exceptions etc.), - performance and
- tight integration with ECMAScript (i.e. the ability to pass objects and call methods back and forth between the two languages).
Unfortunately, when you have to resort to tricks like managing your own stack, doing CPS transforms, building on top of exceptions, … it turns out that you can only pick two of the three goals.
- Ruby has block-level scoping of local variables, JavaScript has function-level scoping
- Ruby's inheritance + mixins would likely be problematic to implement simply using JavaScript's prototypal inheritance
- Ruby's arity checking for method/lambda invocation and is more strict than JavaScript's permissive passing
- Ruby has true, enforced constants; JavaScript may not (depending on which version the interpreter is using)
- Class variables (ugh) have no equivalent in JaveScript, and so will require special handling
- Ruby's has green threads in the core, JavaScript does not
JavaScript is Turing-complete, so theoretically you can implement anything, including other programming languages in it. It doesn't matter how different the implementation (JavaScript) and the target language (Ruby) are. The impedance mismatch between languages like Ruby and C is huge, and there you have Ruby, Python, Perl, and JavaScript itself, all implemented in C.
Implementing Ruby in JavaScript should be orders of magnitude easier than doing so in a lower level language. To your advantage, you have that much of Ruby and Ruby's standard library are written in Ruby itself, so once you get a basic interpreter going, things should gradually be more and more downhill.
Implementing an efficient Ruby interpreter in JavaScript may be harder, but it's still possible. You may end up translating Ruby to JavaScript so the excellent optimizers available can kick in.
So, do not think about the differences between Ruby and JavaScript. Take a look at the standard implementation of Ruby, and think about how you would implement that in JavaScript.
精彩评论