Skip to content

Commit

Permalink
Add Symbol#to_proc to match Ruby 1.8.7
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.codehaus.org/jruby/trunk/jruby@6507 961051c9-f516-0410-bf72-c9f7e237a7b7
  • Loading branch information
olabini committed Apr 16, 2008
1 parent 53e5c20 commit e0eabb8
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
36 changes: 36 additions & 0 deletions src/org/jruby/RubySymbol.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,15 @@
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallBlock;
import org.jruby.runtime.BlockCallback;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.marshal.UnmarshalStream;



/**
* Represents a Ruby symbol (e.g. :bar)
*/
Expand Down Expand Up @@ -190,6 +196,36 @@ public IRubyObject freeze() {
public IRubyObject taint() {
return this;
}

private static class ToProcCallback implements BlockCallback {
private RubySymbol symbol;
public ToProcCallback(RubySymbol symbol) {
this.symbol = symbol;
}

public IRubyObject call(ThreadContext ctx, IRubyObject[] args, Block blk) {
IRubyObject[] currentArgs = args;
if(currentArgs.length == 0) {
throw symbol.getRuntime().newArgumentError("no receiver given");
}
if((currentArgs[0] instanceof RubyArray) && ((RubyArray)currentArgs[0]).getLength() != 0) {
// This is needed to unpack stuff
currentArgs = ((RubyArray)currentArgs[0]).toJavaArrayMaybeUnsafe();
IRubyObject[] args2 = new IRubyObject[currentArgs.length-1];
System.arraycopy(currentArgs, 1, args2, 0, args2.length);
return currentArgs[0].callMethod(ctx, symbol.symbol, args2, Block.NULL_BLOCK);
} else {
return currentArgs[0].callMethod(ctx, symbol.symbol, new IRubyObject[0], Block.NULL_BLOCK);
}
}
}

@JRubyMethod
public IRubyObject to_proc() {
return RubyProc.newProc(getRuntime(),
CallBlock.newCallClosure(this, getRuntime().getSymbol(), Arity.noArguments(), new ToProcCallback(this), getRuntime().getCurrentContext()),
Block.Type.PROC);
}

private static boolean isIdentStart(char c) {
return ((c >= 'a' && c <= 'z')|| (c >= 'A' && c <= 'Z')
Expand Down
24 changes: 23 additions & 1 deletion test/testSymbol.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,26 @@ def x.foo(other)
test_equal(:"abc#{7 + 8 + 9}#{1 + 2 + 3}".inspect, ":abc246")

#Creating a singleton from Symbol should yield: "TypeError: no virtual class for Symbol"
test_exception(TypeError) { class << :abc ; end }
test_exception(TypeError) { class << :abc ; end }

test_ok Symbol.instance_methods.include?('to_proc')
class SymTest
attr_accessor :call_parameters
def call(*args)
self.call_parameters = args
end
end

s = SymTest.new
[s].each &:call
test_equal [], s.call_parameters

s = SymTest.new
[[s,1]].each &:call
test_equal [1], s.call_parameters

s = SymTest.new
[[s,1,2,3]].each &:call
test_equal [1,2,3], s.call_parameters

test_exception ArgumentError, &:call

0 comments on commit e0eabb8

Please sign in to comment.