# = multiton.rb # # == Copyright (c) 2005 Thomas Sawyer # # Ruby License # # This module is free software. You may use, modify, and/or redistribute this # software under the same terms as Ruby. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. # # == Author(s) # # * Thomas Sawyer # Author:: Thomas Sawyer # Copyright:: Copyright (c) 2006 Thomas Sawyer # License:: Ruby License require 'facets/core/kernel/object_class' # = Recorder # # Recorder is similar essentially a method probe. It records everthing # that happens to it, building an internal parse tree. You can then # pass a substitute object and apply the recoding to it. Or you can # utilize the parse tree. # # The only limitation of Recorder is with special operators, like if, &&, ||, etc. # Since they are not true methods they can't be recorded. (Too bad for Ruby.) # # == Synopsis # # class Z # def name ; 'George' ; end # def age ; 12 ; end # end # # z = Z.new # # r = Recorder.new # q = proc { |x| (x.name == 'George') & (x.age > 10) } # x = q[r] # x.__call__(z) # # produces # # true # class Recorder # Privatize all kernel methods. private *instance_methods # def initialize( msg=nil ) @msg = msg end def inspect "" end def __call__( orig ) return orig unless @msg sym = @msg[0] args = @msg[1..-1].collect do |a| Recorder === a ? a.__call__(orig) : a end obj = args.shift obj.__send__( sym, *args ) end def method_missing( sym, *args, &blk ) object_class.new( [ sym, self, *args ] ) end end # _____ _ # |_ _|__ ___| |_ # | |/ _ \/ __| __| # | | __/\__ \ |_ # |_|\___||___/\__| # =begin test require 'test/unit' #class Object # def &(o) # self && o # end #end class TCRecorder < Test::Unit::TestCase class Z def name ; 'George' ; end def age ; 12 ; end end def setup @z = Z.new end def test_001 r = Recorder.new q = proc { |x| (x.name == 'George') & (x.age > 10) } x = q[r] assert( x.__call__(@z) ) end end =end