Skip to content

Commit

Permalink
Implement Module#instance_method and fix Method and UnboundMethod
Browse files Browse the repository at this point in the history
  • Loading branch information
meh committed Oct 1, 2013
1 parent db1091c commit ea98c15
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 11 deletions.
15 changes: 5 additions & 10 deletions corelib/kernel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,13 @@ def <=>(other)

def method(name)
%x{
var recv = #{self},
meth = recv['$' + name],
func = function() {
return meth.apply(recv, $slice.call(arguments, 0));
};
if (!meth) {
#{ raise NameError };
var meth = self['$' + name];
if (!meth || meth.rb_stub) {
#{raise NameError, "undefined method `#{name}' for class `#{self.class.name}'"};
}
func._klass = #{Method};
return func;
return #{Method.new(self, `meth`, name)};
}
end

Expand Down
12 changes: 12 additions & 0 deletions corelib/module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,18 @@ def include(*mods)
}
end

def instance_method(name)
%x{
var meth = self._proto['$' + name];
if (!meth || meth.rb_stub) {
#{raise NameError, "undefined method `wut' for class `#{name}'"};

This comment has been minimized.

Copy link
@DouweM

DouweM Oct 1, 2013

Contributor

You're sure that's right?

This comment has been minimized.

Copy link
@meh

meh Oct 1, 2013

Author Member

Yes, yes it is, totally legit and not a missing interpolation 🐼

This comment has been minimized.

Copy link
@DouweM

DouweM Oct 1, 2013

Contributor

I thought so; just making sure.

}
return #{UnboundMethod.new(self, `meth`, name)};
}
end

def instance_methods(include_super = false)
%x{
var methods = [], proto = #{self}._proto;
Expand Down
59 changes: 58 additions & 1 deletion corelib/proc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,61 @@ def to_n
end
end

class Method < Proc; end
class Method
attr_reader :owner, :receiver, :name

def initialize(receiver, method, name)
@receiver = receiver
@owner = receiver.class
@name = name
@method = method
end

def arity
@method.arity
end

def call(*args, &block)
%x{
#@method._p = block;
return #@method.apply(#@object, args);
}
end

alias [] call

def unbind
UnboundMethod.new(@owner, @method, @name)
end

def to_proc
@method
end

def inspect
"#<Method: #{@obj.class.name}##@name}>"
end
end

class UnboundMethod
attr_reader :owner, :name

def initialize(owner, method, name)
@owner = owner
@method = method
@name = name
end

def arity
@method.arity
end

def bind(object)
Method.new(object, @method, @name)
end

def inspect
"#<UnboundMethod: #{@owner.name}##@name>"
end
end

0 comments on commit ea98c15

Please sign in to comment.