Skip to content

Commit

Permalink
Coroutine support for Enumerator#next and #rewind. Not isolated from …
Browse files Browse the repository at this point in the history
…mainline code yet.
  • Loading branch information
headius committed Jun 14, 2010
1 parent 60f553c commit df56853
Showing 1 changed file with 62 additions and 5 deletions.
67 changes: 62 additions & 5 deletions src/org/jruby/RubyEnumerator.java
Expand Up @@ -30,14 +30,22 @@
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.javasupport.util.RuntimeHelpers;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Binding;
import org.jruby.runtime.Block;
import org.jruby.runtime.Block.Type;
import org.jruby.runtime.BlockCallback;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;

import java.dyn.AsymCoroutine;
import org.jruby.parser.LocalStaticScope;
import org.jruby.runtime.BlockBody;

/**
* Implementation of Ruby's Enumerator module.
*/
Expand Down Expand Up @@ -403,14 +411,63 @@ public static IRubyObject with_index19(ThreadContext context, IRubyObject self,
}

@JRubyMethod(name = "next", frame = true)
public static IRubyObject next(ThreadContext context, IRubyObject self) {
context.getRuntime().getLoadService().lockAndRequire("generator_internal");
return self.callMethod(context, "next");
public static IRubyObject next(final ThreadContext context, final IRubyObject self) {
AsymCoroutine coro = getCoro(self);
if (coro == null) {
coro = setupCoro(context, self);
}
return (IRubyObject)coro.call();
}

@JRubyMethod(name = "rewind", frame = true)
public static IRubyObject rewind(ThreadContext context, IRubyObject self) {
context.getRuntime().getLoadService().lockAndRequire("generator_internal");
return self.callMethod(context, "rewind");
setupCoro(context, self);
return context.getRuntime().getNil();
}

private static AsymCoroutine getCoro(IRubyObject self) {
return (AsymCoroutine)self.getInternalVariables().getInternalVariable("coro");
}

private static AsymCoroutine setupCoro(final ThreadContext context, final IRubyObject self) {
AsymCoroutine coro = new AsymCoroutine<IRubyObject, IRubyObject>() {
public IRubyObject run(IRubyObject value) {
IRubyObject result = self.callMethod(context, "each", IRubyObject.NULL_ARRAY, new Block(new BlockBody(FL_USHIFT) {
@Override
public IRubyObject yield(ThreadContext context, IRubyObject value, Binding binding, Type type) {
return ret(value);
}

@Override
public IRubyObject yield(ThreadContext context, IRubyObject value, IRubyObject self, RubyModule klass, boolean aValue, Binding binding, Type type) {
return ret(value);
}

StaticScope scope = new LocalStaticScope(null);

@Override
public StaticScope getStaticScope() {
return scope;
}

@Override
public void setStaticScope(StaticScope newScope) {
}

@Override
public Block cloneBlock(Binding binding) {
return new Block(this);
}

@Override
public Arity arity() {
return Arity.ONE_ARGUMENT;
}
}));
return result;
}
};
self.getInternalVariables().setInternalVariable("coro", coro);
return coro;
}
}

0 comments on commit df56853

Please sign in to comment.