[macruby-changes] [1422] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Thu Apr 16 18:23:37 PDT 2009


Revision: 1422
          http://trac.macosforge.org/projects/ruby/changeset/1422
Author:   lsansonetti at apple.com
Date:     2009-04-16 18:23:34 -0700 (Thu, 16 Apr 2009)
Log Message:
-----------
work in progress on the new c/objc dispatcher

Modified Paths:
--------------
    MacRuby/branches/experimental/class.c
    MacRuby/branches/experimental/roxor.cpp
    MacRuby/branches/experimental/roxor.h
    MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb
    MacRuby/branches/experimental/vm_method.c

Modified: MacRuby/branches/experimental/class.c
===================================================================
--- MacRuby/branches/experimental/class.c	2009-04-16 05:28:37 UTC (rev 1421)
+++ MacRuby/branches/experimental/class.c	2009-04-17 01:23:34 UTC (rev 1422)
@@ -746,7 +746,8 @@
 }
 
 static void
-rb_objc_push_methods(VALUE ary, VALUE mod, VALUE objc_methods, int (*func) (VALUE, ID, VALUE))
+rb_objc_push_methods(VALUE ary, VALUE mod, VALUE objc_methods,
+		     int (*func) (VALUE, ID, VALUE))
 {
     Method *methods;
     unsigned int i, count;
@@ -770,17 +771,20 @@
 	    method = methods[i];
 
 	    sel = method_getName(method);
-	    if (sel == sel_ignored)
+	    if (sel == sel_ignored) {
 		continue; 
+	    }
 
 	    imp = method_getImplementation(method);
-	    if (imp == NULL)
+	    if (imp == NULL) {
 		continue;
+	    }
 
-	    mn = rb_objc_method_node3(imp);
+	    mn = rb_vm_get_method_node(imp);
 	    is_ruby_method = mn != NULL;
-	    if (!is_ruby_method && objc_methods == Qfalse)
+	    if (!is_ruby_method && objc_methods == Qfalse) {
 		continue;
+	    }
 
 	    sel_name = (char *)sel;
 	    len = strlen(sel_name);
@@ -803,7 +807,7 @@
 			buf[len + 2] = '\0';
 
 			method = class_getInstanceMethod((Class)mod, sel_registerName(buf));
-			if (method != NULL && rb_objc_method_node3(method_getImplementation(method)) == NULL)
+			if (method != NULL && rb_vm_get_method_node(method_getImplementation(method)) == NULL)
 			    continue;
 		    }
 		    else if (sel_name[len - 2] == '?') {
@@ -814,7 +818,7 @@
 			buf[len + 1] = '\0';
 
 			method = class_getInstanceMethod((Class)mod, sel_registerName(buf));
-			if (method != NULL && rb_objc_method_node3(method_getImplementation(method)) == NULL)
+			if (method != NULL && rb_vm_get_method_node(method_getImplementation(method)) == NULL)
 			    continue;
 		    }
 		}
@@ -860,16 +864,19 @@
     }
     else {
 	rb_scan_args(argc, argv, "02", &recur, &objc_methods);
-	if (NIL_P(recur))
+	if (NIL_P(recur)) {
 	    recur = Qtrue;
-	if (NIL_P(objc_methods))
+	}
+	if (NIL_P(objc_methods)) {
 	    objc_methods = Qfalse;
+	}
     }
 
     while (mod != 0) {
 	rb_objc_push_methods(ary, mod, objc_methods, func);
-	if (recur == Qfalse)
+	if (recur == Qfalse) {
 	   break;	   
+	}
 	mod = (VALUE)class_getSuperclass((Class)mod); 
     } 
 

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-04-16 05:28:37 UTC (rev 1421)
+++ MacRuby/branches/experimental/roxor.cpp	2009-04-17 01:23:34 UTC (rev 1422)
@@ -2440,6 +2440,13 @@
     return iter->second->node;
 }
 
+extern "C"
+NODE *
+rb_vm_get_method_node(IMP imp)
+{
+    return GET_VM()->method_node_get(imp);
+}
+
 inline GlobalVariable *
 RoxorVM::redefined_op_gvar(SEL sel, bool create)
 {
@@ -4789,11 +4796,36 @@
     return new LoadInst(slot, "", bb);
 }
 
+extern "C"
+VALUE
+rb_vm_ocval_to_rval(void *ocval)
+{
+    return SPECIAL_CONST_P(ocval) ? (VALUE)ocval : OC2RB(ocval);
+}
+
 Value *
 RoxorCompiler::compile_conversion_to_ruby(const char *type, Value *val)
 {
-    // TODO
-    return val;
+    const char *func_name = NULL;
+
+    switch (*type) {
+	case _C_ID:
+	case _C_CLASS:
+	    func_name = "rb_vm_ocval_to_rval";
+	    break;
+
+	default:
+	    printf("unrecognized compile type `%s' to Ruby - aborting\n", type);
+	    abort();
+    }
+ 
+    std::vector<Value *> params;
+    params.push_back(val);
+
+    Function *func = cast<Function>(module->getOrInsertFunction(
+		func_name, RubyObjTy, convert_type(type), NULL));
+
+    return CallInst::Create(func, params.begin(), params.end(), "", bb);
 }
 
 inline const Type *
@@ -4872,6 +4904,7 @@
     p = SkipFirstType(p);
     f_types.push_back(RubyObjTy);
     params.push_back(self_arg);
+
     // sel
     p = SkipFirstType(p);
     f_types.push_back(PtrTy);
@@ -6121,6 +6154,33 @@
     return stub;
 }
 
+static inline SEL
+helper_sel(SEL sel)
+{
+    const char *p = sel_getName(sel);
+    long len = strlen(p);
+    SEL new_sel = 0;
+    char buf[100];
+
+    if (len >= 3 && isalpha(p[len - 3]) && p[len - 2] == '=' && p[len - 1] == ':') {
+	/* foo=: -> setFoo: shortcut */
+	snprintf(buf, sizeof buf, "set%s", p);
+	buf[3] = toupper(buf[3]);
+	buf[len + 1] = ':';
+	buf[len + 2] = '\0';
+	new_sel = sel_registerName(buf);
+    }
+    else if (isalpha(p[len - 2]) && p[len - 1] == '?') {
+	/* foo?: -> isFoo: shortcut */
+	snprintf(buf, sizeof buf, "is%s", p);
+	buf[2] = toupper(buf[2]);
+	buf[len + 1] = '\0';
+	new_sel = sel_registerName(buf);
+    }
+
+    return new_sel;
+}
+
 __attribute__((always_inline))
 static VALUE
 __rb_vm_dispatch(struct mcache *cache, VALUE self, Class klass, SEL sel, 
@@ -6182,6 +6242,19 @@
 	    }
 	}
 	else {
+	    SEL new_sel = helper_sel(sel);
+	    if (new_sel != NULL) {
+		Method m = class_getInstanceMethod(klass, new_sel);
+		if (m != NULL) {
+		    IMP imp = method_getImplementation(m);
+		    if (GET_VM()->method_node_get(imp) == NULL) {
+			sel = new_sel;
+			method = m;
+			goto recache;	
+		    }
+		}
+	    }
+
 	    // TODO bridgesupport C call?
 	    return method_missing((VALUE)self, sel, argc, argv, opt);
 	}
@@ -6909,12 +6982,23 @@
 	    selRespondTo);
 
     if (respond_to_imp == basic_respond_to_imp) {
-	IMP obj_imp = class_getMethodImplementation((Class)klass, sel);
-	if (obj_imp == NULL) {
+	Method m = class_getInstanceMethod((Class)klass, sel);
+	if (m == NULL) {
+	    sel = helper_sel(sel);
+	    if (sel != NULL) {
+		m = class_getInstanceMethod((Class)klass, sel);
+	    }
+	    if (m == NULL) {
+		return false;
+	    }
+	}
+	IMP obj_imp = method_getImplementation(m);
+        NODE *node = GET_VM()->method_node_get(obj_imp);
+
+	if (node != NULL && priv == 0 && (node->nd_noex & NOEX_PRIVATE)) {
 	    return false;
 	}
-        NODE *node = GET_VM()->method_node_get(obj_imp);
-	return node != NULL && (!priv || !(node->nd_noex & NOEX_PRIVATE));
+        return obj_imp != NULL;
     }
     else {
         VALUE args[2];

Modified: MacRuby/branches/experimental/roxor.h
===================================================================
--- MacRuby/branches/experimental/roxor.h	2009-04-16 05:28:37 UTC (rev 1421)
+++ MacRuby/branches/experimental/roxor.h	2009-04-17 01:23:34 UTC (rev 1422)
@@ -65,6 +65,7 @@
 void rb_vm_const_is_defined(ID path);
 bool rb_vm_lookup_method(Class klass, SEL sel, IMP *pimp, NODE **pnode);
 bool rb_vm_lookup_method2(Class klass, ID mid, SEL *psel, IMP *pimp, NODE **pnode);
+NODE *rb_vm_get_method_node(IMP imp);
 void rb_vm_define_method(Class klass, SEL sel, IMP imp, NODE *node, bool direct);
 void rb_vm_define_attr(Class klass, const char *name, bool read, bool write, int noex);
 void rb_vm_alias(VALUE klass, ID name, ID def);

Modified: MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb
===================================================================
--- MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb	2009-04-16 05:28:37 UTC (rev 1421)
+++ MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb	2009-04-17 01:23:34 UTC (rev 1422)
@@ -19,8 +19,10 @@
     o = Object.new
     def o.foo(x); x; end
     def o.foo(x, withObject:y); x + y; end
+    def o.foo(x, withObject:y, andObject:z); x + y + z; end
     o.respond_to?(:'foo').should == true
     o.respond_to?(:'foo:withObject:').should == true
+    o.respond_to?(:'foo:withObject:andObject:').should == true
   end
 
   it "must start by a regular argument variable then followed by argument-names" do
@@ -71,6 +73,20 @@
     o.performSelector(:'doSomething:withObject:',
                       withObject:40, withObject:2).should == 42
   end
+
+  it "named using the setFoo pattern cannot be called using #foo=" do
+    o = Object.new
+    def o.setFoo(x); end
+    o.respond_to?(:'foo=').should == false
+    lambda { o.foo = 42 }.should raise_error(NoMethodError)
+  end
+
+  it "named using the isFoo pattern cannot be called using #foo?" do
+    o = Object.new
+    def o.isFoo; end
+    o.respond_to?(:'foo?').should == false
+    lambda { o.foo? }.should raise_error(NoMethodError)
+  end
 end
 
 describe "An Objective-C method" do
@@ -91,10 +107,10 @@
 
   it "is only exposed in #methods if the second argument is true" do
     o = Object.new
-    o.methods.include?(:'performSelector:').should == false
-    o.methods(true).include?(:'performSelector:').should == false
-    o.methods(false).include?(:'performSelector:').should == false
-    o.methods(true, true).include?(:'performSelector:').should == true
-    o.methods(false, true).include?(:'performSelector:').should == true
+    o.methods.include?(:'performSelector').should == false
+    o.methods(true).include?(:'performSelector').should == false
+    o.methods(false).include?(:'performSelector').should == false
+    o.methods(true, true).include?(:'performSelector').should == true
+    o.methods(false, true).include?(:'performSelector').should == true
   end
 end

Modified: MacRuby/branches/experimental/vm_method.c
===================================================================
--- MacRuby/branches/experimental/vm_method.c	2009-04-16 05:28:37 UTC (rev 1421)
+++ MacRuby/branches/experimental/vm_method.c	2009-04-17 01:23:34 UTC (rev 1422)
@@ -815,7 +815,7 @@
 	char buf[100];
 	snprintf(buf, sizeof buf, "%s:", id_name);
 	sel = sel_registerName(buf);
-	return rb_vm_respond_to(obj, sel, priv) == true;
+	return rb_vm_respond_to(obj, sel, priv) == true ? 1 : 0;
     }
     return 1;
 }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090416/ddef7e7c/attachment-0001.html>


More information about the macruby-changes mailing list