mirror of
https://github.com/ruby/ruby.git
synced 2025-08-24 13:34:17 +02:00

POSIX_SIGNAL is defined. * eval.c (error_print): errat array may be empty. * eval.c (rb_eval_cmd): should not upgrade safe level unless explicitly specified by argument newly added. * signal.c (sig_trap): should not allow tainted trap closure. * variable.c (rb_f_trace_var): should not allow trace_var on safe level higher than 3. * variable.c (rb_f_trace_var): should not allow tainted trace closure. * gc.c: do not use static stack until system stack overflows. * eval.c (eval): should call Exception#exception instead of calling rb_exc_new3() directly. * error.c (exc_exception): set "mesg" directly to the clone. it might be better to set mesg via some method for flexibility. * variable.c (cvar_override_check): should print original module name, if 'a' is T_ICLASS. * parse.y (yylex): float '1_.0' should not be allowed. * variable.c (var_getter): should care about var as Qfalse (ruby-bugs#PR199). * array.c (cmpint): <=> or block for {min,max} may return bignum. * array.c (sort_1): use rb_compint. * array.c (sort_2): ditto. * enum.c (min_ii): ditto. * enum.c (min_ii): ditto. * enum.c (max_i): ditto. * enum.c (max_ii): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1826 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
128 lines
2.6 KiB
Ruby
128 lines
2.6 KiB
Ruby
# Delegation class that delegates even methods defined in super class,
|
|
# which can not be covered with normal method_missing hack.
|
|
#
|
|
# Delegator is the abstract delegation class. Need to redefine
|
|
# `__getobj__' method in the subclass. SimpleDelegator is the
|
|
# concrete subclass for simple delegation.
|
|
#
|
|
# Usage:
|
|
# foo = Object.new
|
|
# foo2 = SimpleDelegator.new(foo)
|
|
# foo.hash == foo2.hash # => false
|
|
#
|
|
# Foo = DelegateClass(Array)
|
|
#
|
|
# class ExtArray<DelegateClass(Array)
|
|
# ...
|
|
# end
|
|
|
|
class Delegator
|
|
|
|
def initialize(obj)
|
|
preserved = ::Kernel.instance_methods
|
|
preserved -= ["to_s","to_a","inspect","==","=~","==="]
|
|
for t in self.type.ancestors
|
|
preserved |= t.instance_methods
|
|
preserved |= t.private_instance_methods
|
|
preserved |= t.protected_instance_methods
|
|
break if t == Delegator
|
|
end
|
|
for method in obj.methods
|
|
next if preserved.include? method
|
|
begin
|
|
eval <<-EOS
|
|
def self.#{method}(*args, &block)
|
|
begin
|
|
__getobj__.__send__(:#{method}, *args, &block)
|
|
rescue Exception
|
|
$@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
|
|
$@.delete_if{|s| /^\\(eval\\):/ =~ s}
|
|
raise
|
|
end
|
|
end
|
|
EOS
|
|
rescue SyntaxError
|
|
raise NameError, "invalid identifier %s" % method, caller(4)
|
|
end
|
|
end
|
|
end
|
|
|
|
def __getobj__
|
|
raise NotImplementError, "need to define `__getobj__'"
|
|
end
|
|
|
|
end
|
|
|
|
class SimpleDelegator<Delegator
|
|
|
|
def initialize(obj)
|
|
super
|
|
@obj = obj
|
|
end
|
|
|
|
def __getobj__
|
|
@obj
|
|
end
|
|
|
|
def __setobj__(obj)
|
|
@obj = obj
|
|
end
|
|
end
|
|
|
|
# backward compatibility ^_^;;;
|
|
Delegater = Delegator
|
|
SimpleDelegater = SimpleDelegator
|
|
|
|
#
|
|
def DelegateClass(superclass)
|
|
klass = Class.new
|
|
methods = superclass.instance_methods
|
|
methods -= ::Kernel.instance_methods
|
|
methods |= ["to_s","to_a","inspect","==","=~","==="]
|
|
klass.module_eval <<-EOS
|
|
def initialize(obj)
|
|
@obj = obj
|
|
end
|
|
EOS
|
|
for method in methods
|
|
begin
|
|
klass.module_eval <<-EOS
|
|
def #{method}(*args, &block)
|
|
begin
|
|
@obj.__send__(:#{method}, *args, &block)
|
|
rescue
|
|
$@[0,2] = nil
|
|
raise
|
|
end
|
|
end
|
|
EOS
|
|
rescue SyntaxError
|
|
raise NameError, "invalid identifier %s" % method, caller(3)
|
|
end
|
|
end
|
|
return klass;
|
|
end
|
|
|
|
if __FILE__ == $0
|
|
class ExtArray<DelegateClass(Array)
|
|
def initialize()
|
|
super([])
|
|
end
|
|
end
|
|
|
|
ary = ExtArray.new
|
|
p ary.type
|
|
ary.push 25
|
|
p ary
|
|
|
|
foo = Object.new
|
|
def foo.test
|
|
25
|
|
end
|
|
def foo.error
|
|
raise 'this is OK'
|
|
end
|
|
foo2 = SimpleDelegator.new(foo)
|
|
p foo.test == foo2.test # => true
|
|
foo2.error # raise error!
|
|
end
|