Powered by: newtelligence dasBlog 1.9.7067.0
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2008 , Ted Neward
E-mail
Larry O'Brien asks
Are you confident that continuations can be even semi-efficiently implemented on the CLR? I'm not.
If Microsoft thinks Ruby is important, they're ignoring the threat to them posed by X (where, I suspect, X = LISP), or If Microsoft thinks Ruby is competition, they will not implement it and therefore be doomed Not long ago, Microsoft posted a job opening for a developer "first task will be to drive the exploration of other dynamic languages such as Ruby and JavaScript on the CLR", so my feeling is that if Microsoft could get a Ruby on the CLR, they'd be thrilled.
Larry goes on to say:
Ruby is not easy to implement on the CLR, at least in part because a complete Ruby implementation requires continuations, which are not modeled within the CLR. This isn't just laziness on the part of langauge implementors. The CLR presents a machine architecture different than the wide-open architecture in which most compiler experience has been gathered. The CLR architecture is safer, but more restrictive, when it comes to manipulating the stack, which is central to continuations.
Continuations are not impossible to support, however they are currently more or less impossible to support given the current lack of access to the underlying stack frames in the managed environment--you'd need some support from the runtimes (either the JVM or the CLR) to make it work. Such runtime support would not be too difficult to add, however, as both environments already have rich and powerful stack-walking mechanisms (because both environments use the thread stack as bookkeeping tools, among other things, and need to be able to crawl through those stack markers for a variety of reasons, such as security checks), and it would not be hard to create a runtime-level mechanism that allowed code to "take a snapshot" of the stack--and its related object graph--from a certain point to a certain point, and save off that state to some arbitrary location. In many respects, it would be similar to serializing an object, I believe. In fact, we could imagine something along the lines of:
// All this is totally C#-like pseudocode. Imagine // something similar for Java if you like. // public int ContinuationedMethod() { SnapshotMarker sm = new SnapshotMarker(); // in other words, the StackSnapshot will only crawl // back to the SnapshotMarker referenced when we // take the thread's snapshot; this way we don't crawl // all the way back to the Thread's starting point (unless // you really wanted to). int x = 1; for (int i=0; i<10; i++) { x = x * i; if (i == 5) { StackSnapshot ss = Thread.Current.TakeSnapshot(sm); // At this point, the managed stack is walked, heap-referenced // objects are captured, the instruction label that we're on is // saved, and a StackSnapshot is allocated and returned. // However, when ss is later rehydrated--using, say, ss.Resume(), // we need some way of knowing that. So, following the lead of the // old Unix fork() call, I presume that a "null" return value from // TakeSnapshot is our way of knowing that we are resuming. // if (ss == null) continue; else { // store ss someplace for later retrieval and return, either by // throwing an exception if you like or just plain-old-"return 0" // or something // } } } return x; }
In the end, continuations are not, I believe, nearly as hard to implement--on either the JVM or the CLR--as some might suggest. Had I the money, I would go off and build the necessary Ruby-esque features we'd want into the CLR (through Rotor) or the JVM (through... uh... the JCL source, I guess, though the licensing there bothers me) for use. Anybody got some cash laying around to cover my mortgage while I do this?