Charles O Nutter wrote: > > > - Methods are compiled to produce least call overhead and minimum > classes; rather than a class per method, there's stubbing and interface > tricks that can be pulled > - Methods would ideally be direct calls > - Local variables, including arguments, would be maintained as frames on > a thread-local stack; variable reads and writes would manipulate array > offsets into that frame stack > - Blocks would hold references back to the frames on that stack, > delegating appropriate variables to each level. A hierarchical data > structure could be built to provide O(1) access times to all variables > in a block's scope hierarchy > - Tail calls would simply reuse the top frame on the stack, expanding or > shrinking it as necessary, setting the new call's args as appropriate > and clearing the local var frame before execution > > I can see how to make all of this work...it's mostly just a matter of > time and patience refactoring the system to use completely new > call/arg/var mechanisms without breaking it :) But hey, it oughta be a > lot of fun, right? >
Hi, Let's see if I understand more or less how this would work. The block closures seem to be more or less like how lexical variables in Lisp are usually compiled. If we have this in a file, called foobar.rb: class String def testOne(param1) @abc = "tttoo" @@baz = :arg index = 0 each_byte { |b| index+=1 0.upto(index) {|i| puts index,i} } end end "str".testOne(:fux) And this could get compiled more or less into a class looking somewhat like this: public class FoobarRubyFile { public IRubyObject testOne(IRuby runtime, IRubyObject self, IRubyObject param1) { self.instanceVariableSet("abc",runtime.newString("tttoo")); self.singletonVariableSet("baz",runtime.newSymbol("arg")); IRubyObject[] frame = new IRubyObject[1]; runtime.pushFrame(frame); frame[0] = RubyFixnum.zero(runtime); IRubyObject retval = self.each_byte(runtime,new Block1(runtime,self)); runtime.popFrame(); return retval; } public static class Block1 implements Block { private IRuby runtime; private IRubyObject enclosing_self; public Block1(IRuby runtime, IRubyObject e_self) { this.runtime = runtime, this.enclosing_self = e_self; } public IRubyObject invoke(IRubyObject[] args) { runtime.pushFrame(args); runtime.getFrame(1)[0].invokeMethod("+=",RubyFixnum.one(runtime)); IRubyObject retval = RubyFixnum.zero(runtime).invokeMethod("upto",runtime.getFrame(1)[0],new Block2(runtime,enclosing_self)); runtime.popFrame(); return retval; } } public static class Block2 implements Block { private IRuby runtime; private IRubyObject enclosing_self; public Block2(IRuby runtime, IRubyObject e_self) { this.runtime = runtime, this.enclosing_self = e_self; } public IRubyObject invoke(IRubyObject[] args) { runtime.pushFrame(args); IRubyObject retval = runtime.invokeMethod("puts",new IRubyObject[]{runtime.getFrame(2)[0], args[0]}) runtime.popFrame(); return retval; } } public IRubyObject jruby_run(final IRuby runtime) { IRubyObject[] frame = new IRubyObject[2]; runtime.pushFrame(frame); RubyClass clsString = runtime.getOrDefineClass("String"); clsString.defineMethod("testOne",RubyArity.ONE,getClass().getMethod("testOne",null)); frame[0] = runtime.newString("str"); frame[1] = runtime.newSymbol("fux"); IRubyObject retval = testOne(runtime,frame[0],frame[1]); runtime.popFrame(); return retval; } } What's going on here is probably quite easy to see. All instance and singleton variables have to go through methods on the self-object. The local variables on the other hand gets translated into frames and pushed and popped from the global stack for these frames. In that way any block can refer to a lexical variable through it's index in the stack, and index in the array. There's of course lots of room for improvement in this scheme, especially if the compiler is smart enough to just translate the bits needed, insert good real java calls etc. If I haven't gotten anything really wrong, I think this approach is really good. The two things I don't see how to do clearly with this system is real closures and stack depth. I guess you could do some kind of analysis when creating the block instance and create the closure from that, so that's probably not a big problem. But the deepening of the stack still seems to happen with this system. -- Ola Bini (http://ola-bini.blogspot.com) JvYAML, RbYAML, JRuby and Jatha contributor System Developer, Karolinska Institutet (http://www.ki.se) OLogix Consulting (http://www.ologix.com) "Yields falsehood when quined" yields falsehood when quined. ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Jruby-devel mailing list Jruby-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jruby-devel