[macruby-changes] [3140] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Dec 21 04:34:49 PST 2009


Revision: 3140
          http://trac.macosforge.org/projects/ruby/changeset/3140
Author:   joshua.ballanco at apple.com
Date:     2009-12-21 04:34:46 -0800 (Mon, 21 Dec 2009)
Log Message:
-----------
Enable aliasing of Objective-C methods

Modified Paths:
--------------
    MacRuby/trunk/spec/macruby/core/array_spec.rb
    MacRuby/trunk/spec/macruby/core/hash_spec.rb
    MacRuby/trunk/spec/macruby/core/string_spec.rb
    MacRuby/trunk/spec/macruby/language/objc_method_spec.rb
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h

Modified: MacRuby/trunk/spec/macruby/core/array_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/core/array_spec.rb	2009-12-19 01:50:51 UTC (rev 3139)
+++ MacRuby/trunk/spec/macruby/core/array_spec.rb	2009-12-21 12:34:46 UTC (rev 3140)
@@ -79,3 +79,49 @@
   end
 =end
 end
+
+describe "Objective-C Array methods" do
+  before :each do
+    @a = [1,2,3,4]
+  end
+
+  it "should be able to be aliased to other selectors" do
+    class << @a
+      alias :foo :count
+    end
+
+    @a.foo.should == @a.count
+  end
+
+  it "should be able to be aliased by pure Ruby methods" do
+    class << @a
+      def foo
+        return 42
+      end
+      alias :count :foo
+    end
+
+    @a.count.should == 42
+  end
+
+  it "should be commutative when aliased" do
+    class << @a
+      def foo
+        return 42
+      end
+      def do_alias
+        alias :old_count :count
+        alias :count :foo
+      end
+      def undo_alias
+        alias :count :old_count
+      end
+    end
+
+    @a.count.should == 4
+    @a.do_alias
+    @a.count.should == 42
+    @a.undo_alias
+    @a.count.should == 4
+  end
+end

Modified: MacRuby/trunk/spec/macruby/core/hash_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/core/hash_spec.rb	2009-12-19 01:50:51 UTC (rev 3139)
+++ MacRuby/trunk/spec/macruby/core/hash_spec.rb	2009-12-21 12:34:46 UTC (rev 3140)
@@ -77,3 +77,49 @@
     lambda { a[42] = 123 }.should raise_error(RuntimeError)
   end
 end
+
+describe "Objective-C Hash methods" do
+  before :each do
+    @a = {:a => 1, :b => 2, :c => 3}
+  end
+
+  it "should be able to be aliased to other selectors" do
+    class << @a
+      alias :foo :count
+    end
+
+    @a.foo.should == @a.count
+  end
+
+  it "should be able to be aliased by pure Ruby methods" do
+    class << @a
+      def foo
+        return 42
+      end
+      alias :count :foo
+    end
+
+    @a.count.should == 42
+  end
+
+  it "should be commutative when aliased" do
+    class << @a
+      def foo
+        return 42
+      end
+      def do_alias
+        alias :old_count :count
+        alias :count :foo
+      end
+      def undo_alias
+        alias :count :old_count
+      end
+    end
+
+    @a.count.should == 4
+    @a.do_alias
+    @a.count.should == 42
+    @a.undo_alias
+    @a.count.should == 4
+  end
+end

Modified: MacRuby/trunk/spec/macruby/core/string_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/core/string_spec.rb	2009-12-19 01:50:51 UTC (rev 3139)
+++ MacRuby/trunk/spec/macruby/core/string_spec.rb	2009-12-21 12:34:46 UTC (rev 3140)
@@ -81,3 +81,49 @@
     #lambda { a << 'foo' }.should raise_error(RuntimeError)
   end
 end
+
+describe "Objective-C String methods" do
+  before :each do
+    @a = "test"
+  end
+
+  it "should be able to be aliased to other selectors" do
+    class << @a
+      alias :foo :length
+    end
+
+    @a.foo.should == @a.length
+  end
+
+  it "should be able to be aliased by pure Ruby methods" do
+    class << @a
+      def foo
+        return 42
+      end
+      alias :length :foo
+    end
+
+    @a.length.should == 42
+  end
+
+  it "should be commutative when aliased" do
+    class << @a
+      def foo
+        return 42
+      end
+      def do_alias
+        alias :old_length :length
+        alias :length :foo
+      end
+      def undo_alias
+        alias :length :old_length
+      end
+    end
+
+    @a.length.should == 4
+    @a.do_alias
+    @a.length.should == 42
+    @a.undo_alias
+    @a.length.should == 4
+  end
+end

Modified: MacRuby/trunk/spec/macruby/language/objc_method_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/language/objc_method_spec.rb	2009-12-19 01:50:51 UTC (rev 3139)
+++ MacRuby/trunk/spec/macruby/language/objc_method_spec.rb	2009-12-21 12:34:46 UTC (rev 3140)
@@ -408,6 +408,49 @@
     end
     @o.methodAcceptingSEL('foo:arg1:arg2:', target:o)
   end
+
+  it "can have another method aliased to it" do
+    class << @o
+      alias :test_method :methodReturningSelf
+    end
+
+    @o.should.respond_to(:test_method)
+    @o.test_method.should == @o
+    @o.test_method.object_id.should == @o.object_id
+  end
+
+  it "can be aliased to a pure Ruby method" do
+    class << @o
+      def foo
+        return 42
+      end
+      alias :methodReturningSelf :foo
+    end
+
+    @o.should.respond_to(:methodReturningSelf)
+    @o.methodReturningSelf.should == 42
+  end
+
+  it "should be commutative when aliased" do
+    class << @o
+      def foo
+        return 42
+      end
+      def do_alias
+        alias :old_methodReturningSelf :methodReturningSelf
+        alias :methodReturningSelf :foo
+      end
+      def undo_alias
+        alias :methodReturningSelf :old_methodReturningSelf
+      end
+    end
+
+    @o.methodReturningSelf.should == @o
+    @o.do_alias
+    @o.methodReturningSelf.should == 42
+    @o.undo_alias
+    @o.methodReturningSelf.should == @o
+  end
 end
 
 describe "A pure MacRuby method" do

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-12-19 01:50:51 UTC (rev 3139)
+++ MacRuby/trunk/vm.cpp	2009-12-21 12:34:46 UTC (rev 3140)
@@ -1464,11 +1464,6 @@
     const char *types = method_getTypeEncoding(method);
 
     rb_vm_method_node_t *node = GET_CORE()->method_node_get(method);
-    if (node == NULL) {
-	rb_raise(rb_eArgError,
-		"only pure Ruby methods can be aliased (`%s' is not)",
-		sel_getName(method_getName(method)));
-    }
 
     const char *name_str = rb_id2name(name);
     SEL sel;
@@ -1481,8 +1476,27 @@
 	sel = sel_registerName(tmp);
     }
 
-    GET_CORE()->add_method(klass, sel, imp, node->ruby_imp,
-	    node->arity, node->flags, types);
+    if (node == NULL) {
+      Method method_to_replace = class_getInstanceMethod(klass, sel);
+      rb_vm_method_node_t *node_to_replace = GET_CORE()->method_node_get(method_to_replace);
+      if ((klass == (Class)rb_cCFString || klass == (Class)rb_cCFHash)
+          && node_to_replace != NULL) {
+        //Doesn't work:
+        //GET_CORE()->remove_method(klass, sel);
+        //
+        //This, apparently, doesn't work either...
+        //GET_CORE()->add_method(klass, sel, imp, imp,
+        //   arity, 0, types);
+        //
+        //This...sorta...works...
+        GET_CORE()->nuke_method(method_to_replace);
+      }
+      class_replaceMethod(klass, sel, imp, types);
+    }
+    else {
+      GET_CORE()->add_method(klass, sel, imp, node->ruby_imp,
+          node->arity, node->flags, types);
+    }
 }
 
 extern "C"
@@ -1503,6 +1517,15 @@
 
     const char *def_str = rb_id2name(def);
     SEL sel = sel_registerName(def_str);
+
+    // String and Hash aliases should be defined on the Core Foundation classes
+    if (klass == (Class)rb_cNSMutableString) {
+      klass = (Class)rb_cCFString;
+    }
+    if (klass == (Class)rb_cNSMutableHash) {
+      klass = (Class)rb_cCFHash;
+    }
+
     Method def_method1 = class_getInstanceMethod(klass, sel);
     Method def_method2 = NULL;
     if (def_str[strlen(def_str) - 1] != ':') {
@@ -2535,6 +2558,16 @@
     }
 }
 
+void
+RoxorCore::nuke_method(Method m)
+{
+  invalidate_method_cache(method_getName(m));
+  std::map<Method, rb_vm_method_node_t *>::iterator iter = ruby_methods.find(m);
+  assert(iter != ruby_methods.end());
+  free(iter->second);
+  ruby_methods.erase(iter);
+}
+
 extern "C"
 void
 rb_vm_undef_method(Class klass, ID name, bool must_exist)

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2009-12-19 01:50:51 UTC (rev 3139)
+++ MacRuby/trunk/vm.h	2009-12-21 12:34:46 UTC (rev 3140)
@@ -757,6 +757,7 @@
 		rb_vm_method_node_t *node, const char *types);
 	void undef_method(Class klass, SEL sel);
 	void remove_method(Class klass, SEL sel);
+  void nuke_method(Method m);
 	bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
 		Class klass, SEL sel);
 	bool copy_method(Class klass, Method m);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091221/005adcbe/attachment.html>


More information about the macruby-changes mailing list