[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