Permalink
Browse files

add overloadable

  • Loading branch information...
1 parent 83d36f4 commit e88aff2bf04146964101f55367c3bcab4289235e @JoshCheek JoshCheek committed Feb 6, 2011
@@ -0,0 +1,37 @@
+Description
+===========
+
+I was looking at the platypus interface http://rubyworks.github.com/platypus/docs/api/index.html and thought it would be a fun exercise to try implementing code to make it work.
+
+Usage
+=====
+
+ $ ruby example.rb
+
+---------------------------------------
+
+**This code is unmaintained.**
+
+_If you do something interesting with it, let me know so I can be happy._
+
+---------------------------------------
+
+Copyright (c) 2010 Joshua Cheek
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
@@ -0,0 +1,35 @@
+$: << File.dirname(__FILE__) + "/lib"
+
+require 'overloadable'
+
+class X
+ include Overloadable
+
+ def f
+ "f"
+ end
+
+ sig Integer
+
+ def f(i)
+ "f#{i}"
+ end
+
+ sig String, String
+
+ def f(s1, s2)
+ [s1, s2].join('+')
+ end
+end
+
+x = X.new
+
+p !!x.respond_to?(:f)
+p x.f
+p x.f(1)
+p x.f("A","B")
+
+# >> true
+# >> "f"
+# >> "f1"
+# >> "A+B"
@@ -0,0 +1,4 @@
+require 'overloadable/overloadable'
+require 'overloadable/signature'
+require 'overloadable/overloaded_method'
+require 'overloadable/class_methods'
@@ -0,0 +1,31 @@
+module Overloadable
+ module ClassMethods
+
+ def overloaded_methods
+ @overloaded_methods ||= Hash.new { |hash,methname| hash[methname] = OverloadedMethod.new }
+ end
+
+ def overloaded?(meth)
+ overloaded_methods[meth]
+ end
+
+ def invoke_overloaded( obj , methname , *args , &block )
+ @overloaded_methods[methname].invoke_for(obj,*args,&block)
+ end
+
+ def method_added(methname)
+ overloaded_methods[methname].add current_sig , instance_method(methname)
+ remove_method methname
+ end
+
+ def sig(*types)
+ @current_sig = Signature.new(types)
+ end
+
+ def current_sig
+ @current_sig ||= Signature.new(nil)
+ end
+
+ end
+end
+
@@ -0,0 +1,19 @@
+module Overloadable
+
+ def self.included( klass )
+ klass.extend Overloadable::ClassMethods
+ end
+
+ def method_missing(meth,*args,&block)
+ if self.class.overloaded?(meth)
+ self.class.invoke_overloaded( self , meth , *args , &block )
+ else
+ super
+ end
+ end
+
+ def respond_to?(meth)
+ self.class.overloaded?(meth) || super
+ end
+
+end
@@ -0,0 +1,23 @@
+module Overloadable
+ class OverloadedMethod
+
+ def methods
+ @methods ||= Array.new
+ end
+
+ def add( signature , method )
+ methods << [ signature , method ]
+ end
+
+ def invoke_for( obj , *args , &block )
+ get_method_for(*args,&block).bind(obj).call(*args,&block)
+ end
+
+ def get_method_for( *args , &block )
+ methods.find do |sig,meth|
+ sig.match?(*args,&block)
+ end.last
+ end
+
+ end
+end
@@ -0,0 +1,19 @@
+module Overloadable
+ class Signature
+
+ attr_accessor :types
+
+ def initialize types
+ self.types = types
+ end
+
+ def match?( *args , &block )
+ if types
+ types.size == args.size && types.zip(args).all? { |type,arg| arg.kind_of? type }
+ else
+ args.empty?
+ end
+ end
+
+ end
+end

0 comments on commit e88aff2

Please sign in to comment.