[macruby-changes] [1623] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Thu May 28 13:38:11 PDT 2009
Revision: 1623
http://trac.macosforge.org/projects/ruby/changeset/1623
Author: lsansonetti at apple.com
Date: 2009-05-28 13:38:09 -0700 (Thu, 28 May 2009)
Log Message:
-----------
implemented informal protocol method definition + some refactoring
Modified Paths:
--------------
MacRuby/branches/experimental/bridgesupport.cpp
MacRuby/branches/experimental/objc.h
MacRuby/branches/experimental/objc.m
MacRuby/branches/experimental/spec/macruby/fixtures/method.bridgesupport
MacRuby/branches/experimental/spec/macruby/fixtures/method.m
MacRuby/branches/experimental/spec/macruby/fixtures/method.rb
MacRuby/branches/experimental/spec/macruby/language/objc_method_spec.rb
MacRuby/branches/experimental/vm.cpp
MacRuby/branches/experimental/vm.h
Modified: MacRuby/branches/experimental/bridgesupport.cpp
===================================================================
--- MacRuby/branches/experimental/bridgesupport.cpp 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/bridgesupport.cpp 2009-05-28 20:38:09 UTC (rev 1623)
@@ -827,20 +827,15 @@
case BS_ELEMENT_INFORMAL_PROTOCOL_METHOD:
{
-#if 0
bs_element_informal_protocol_method_t *bs_inf_prot_method =
(bs_element_informal_protocol_method_t *)value;
- struct st_table *t = bs_inf_prot_method->class_method
- ? bs_inf_prot_cmethods
- : bs_inf_prot_imethods;
- st_insert(t, (st_data_t)bs_inf_prot_method->name,
- (st_data_t)bs_inf_prot_method->type);
+ std::map<SEL, std::string> &map =
+ bs_inf_prot_method->class_method
+ ? GET_VM()->bs_informal_protocol_cmethods
+ : GET_VM()->bs_informal_protocol_imethods;
- free(bs_inf_prot_method->protocol_name);
- free(bs_inf_prot_method);
- do_not_free = true;
-#endif
+ map[bs_inf_prot_method->name] = bs_inf_prot_method->type;
break;
}
Modified: MacRuby/branches/experimental/objc.h
===================================================================
--- MacRuby/branches/experimental/objc.h 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/objc.h 2009-05-28 20:38:09 UTC (rev 1623)
@@ -1,3 +1,11 @@
+/*
+ * MacRuby ObjC helpers.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2009, Apple Inc. All rights reserved.
+ */
+
#ifndef __OBJC_H_
#define __OBJC_H_
@@ -12,16 +20,14 @@
unsigned int argc;
};
-bs_element_method_t * rb_bs_find_method(Class klass, SEL sel);
-
-bool rb_objc_get_types(VALUE recv, Class klass, SEL sel,
+bool rb_objc_get_types(VALUE recv, Class klass, SEL sel, Method m,
bs_element_method_t *bs_method, char *buf, size_t buflen);
VALUE rb_objc_call(VALUE recv, SEL sel, int argc, VALUE *argv);
VALUE rb_objc_call2(VALUE recv, VALUE klass, SEL sel, IMP imp,
- struct rb_objc_method_sig *sig, bs_element_method_t *bs_method, int argc,
- VALUE *argv);
+ struct rb_objc_method_sig *sig, bs_element_method_t *bs_method,
+ int argc, VALUE *argv);
void rb_objc_define_kvo_setter(VALUE klass, ID mid);
void rb_objc_change_ruby_method_signature(VALUE mod, ID mid, VALUE sig);
@@ -33,14 +39,16 @@
method = class_getInstanceMethod(klass, sel);
if (method == NULL) {
- printf("method %s not found on class %p - aborting\n", sel_getName(sel), klass);
+ printf("method %s not found on class %p - aborting\n",
+ sel_getName(sel), klass);
abort();
}
assert(method != NULL);
method2 = class_getInstanceMethod((Class)RCLASS_SUPER(klass), sel);
if (method == method2) {
- assert(class_addMethod(klass, sel, imp, method_getTypeEncoding(method)));
+ assert(class_addMethod(klass, sel, imp,
+ method_getTypeEncoding(method)));
}
else {
method_setImplementation(method, imp);
@@ -73,10 +81,12 @@
rb_objc_is_placeholder(id obj)
{
void *klass = *(void **)obj;
- return klass == placeholder_String || klass == placeholder_Dictionary || klass == placeholder_Array;
+ return klass == placeholder_String || klass == placeholder_Dictionary
+ || klass == placeholder_Array;
}
-bool rb_objc_symbolize_address(void *addr, void **start, char *name, size_t name_len);
+bool rb_objc_symbolize_address(void *addr, void **start, char *name,
+ size_t name_len);
static inline int
SubtypeUntil(const char *type, char end)
Modified: MacRuby/branches/experimental/objc.m
===================================================================
--- MacRuby/branches/experimental/objc.m 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/objc.m 2009-05-28 20:38:09 UTC (rev 1623)
@@ -1,29 +1,9 @@
-/*
- * Copyright (c) 2008, Apple Inc. All rights reserved.
+/*
+ * MacRuby ObjC helpers.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2009, Apple Inc. All rights reserved.
*/
#include <Foundation/Foundation.h>
@@ -67,14 +47,12 @@
}
bool
-rb_objc_get_types(VALUE recv, Class klass, SEL sel,
+rb_objc_get_types(VALUE recv, Class klass, SEL sel, Method method,
bs_element_method_t *bs_method, char *buf, size_t buflen)
{
- Method method;
const char *type;
unsigned i;
- method = class_getInstanceMethod(klass, sel);
if (method != NULL) {
if (bs_method == NULL) {
type = method_getTypeEncoding(method);
Modified: MacRuby/branches/experimental/spec/macruby/fixtures/method.bridgesupport
===================================================================
--- MacRuby/branches/experimental/spec/macruby/fixtures/method.bridgesupport 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/spec/macruby/fixtures/method.bridgesupport 2009-05-28 20:38:09 UTC (rev 1623)
@@ -21,4 +21,8 @@
<arg index='0' type='B'/>
</method>
</class>
+ <informal_protocol name='Foo'>
+ <method type="i@:i" selector="informalProtocolMethod1:"/>
+ <method type="B@:ii" selector="informalProtocolMethod2:withValue:"/>
+ </informal_protocol>
</signatures>
Modified: MacRuby/branches/experimental/spec/macruby/fixtures/method.m
===================================================================
--- MacRuby/branches/experimental/spec/macruby/fixtures/method.m 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/spec/macruby/fixtures/method.m 2009-05-28 20:38:09 UTC (rev 1623)
@@ -1,5 +1,12 @@
#import <Foundation/Foundation.h>
+ at interface NSObject (TestInformalProtocolMethod)
+
+- (int)informalProtocolMethod1:(int)arg;
+- (BOOL)informalProtocolMethod2:(int)arg1 withValue:(int)arg2;
+
+ at end
+
@interface TestMethod : NSObject
{
id _foo;
@@ -665,6 +672,16 @@
return ptr == NULL;
}
++ (BOOL)testInformalProtocolMethod1:(id)o
+{
+ return [o informalProtocolMethod1:41] == 42;
+}
+
++ (BOOL)testInformalProtocolMethod2:(id)o
+{
+ return [o informalProtocolMethod2:40 withValue:2];
+}
+
@end
void
Modified: MacRuby/branches/experimental/spec/macruby/fixtures/method.rb
===================================================================
--- MacRuby/branches/experimental/spec/macruby/fixtures/method.rb 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/spec/macruby/fixtures/method.rb 2009-05-28 20:38:09 UTC (rev 1623)
@@ -58,3 +58,12 @@
def methodAcceptingInt(a, float:a2, double:a3, short:a4, NSPoint:a5,
NSRect:a6, char:a7); super; end
end
+
+class TestInformalProtocolMethod
+ def informalProtocolMethod1(x)
+ x + 1
+ end
+ def informalProtocolMethod2(x, withValue:x2)
+ x + x2 == 42
+ end
+end
Modified: MacRuby/branches/experimental/spec/macruby/language/objc_method_spec.rb
===================================================================
--- MacRuby/branches/experimental/spec/macruby/language/objc_method_spec.rb 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/spec/macruby/language/objc_method_spec.rb 2009-05-28 20:38:09 UTC (rev 1623)
@@ -628,3 +628,14 @@
TestMethodOverride.testMethodAcceptingComplexTypes(@o).should == 1
end
end
+
+describe "A pure MacRuby method" do
+ before :each do
+ @o = TestInformalProtocolMethod.new
+ end
+
+ it "whose selector matches an informal protocol is defined on the Objective-C side with the correct type encoding" do
+ TestMethod.testInformalProtocolMethod1(@o).should == 1
+ TestMethod.testInformalProtocolMethod2(@o).should == 1
+ end
+end
Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/vm.cpp 2009-05-28 20:38:09 UTC (rev 1623)
@@ -1119,35 +1119,53 @@
return -1;
}
-static void
-resolve_method(Class klass, SEL sel, Function *func, NODE *node, IMP imp,
- Method m)
+static inline void
+resolve_method_type(char *buf, const size_t buflen, Class klass, Method m,
+ SEL sel, const unsigned int oc_arity)
{
- const int oc_arity = rb_vm_node_arity(node).real + 3;
-
- char types[100];
bs_element_method_t *bs_method = GET_VM()->find_bs_method(klass, sel);
- if (m == NULL || !rb_objc_get_types(Qnil, klass, sel, bs_method, types,
- sizeof types)) {
- assert((unsigned int)oc_arity < sizeof(types));
- types[0] = '@';
- types[1] = '@';
- types[2] = ':';
- for (int i = 3; i < oc_arity; i++) {
- types[i] = '@';
+ if (m == NULL
+ || !rb_objc_get_types(Qnil, klass, sel, m, bs_method, buf, buflen)) {
+
+ std::map<SEL, std::string> &map = class_isMetaClass(klass)
+ ? GET_VM()->bs_informal_protocol_cmethods
+ : GET_VM()->bs_informal_protocol_imethods;
+
+ std::map<SEL, std::string>::iterator iter = map.find(sel);
+ if (iter != map.end()) {
+ strncpy(buf, iter->second.c_str(), sizeof buf);
}
- types[oc_arity] = '\0';
+ else {
+ assert(oc_arity < buflen);
+ buf[0] = '@';
+ buf[1] = '@';
+ buf[2] = ':';
+ for (unsigned int i = 3; i < oc_arity; i++) {
+ buf[i] = '@';
+ }
+ buf[oc_arity] = '\0';
+ }
}
else {
- const int m_argc = method_getNumberOfArguments(m);
+ const unsigned int m_argc = method_getNumberOfArguments(m);
if (m_argc < oc_arity) {
- for (int i = m_argc; i < oc_arity; i++) {
- strcat(types, "@");
+ for (unsigned int i = m_argc; i < oc_arity; i++) {
+ strcat(buf, "@");
}
}
}
+}
+static void
+resolve_method(Class klass, SEL sel, Function *func, NODE *node, IMP imp,
+ Method m)
+{
+ const int oc_arity = rb_vm_node_arity(node).real + 3;
+
+ char types[100];
+ resolve_method_type(types, sizeof types, klass, m, sel, oc_arity);
+
std::map<Function *, IMP>::iterator iter =
GET_VM()->objc_to_ruby_stubs.find(func);
IMP objc_imp;
@@ -1607,23 +1625,11 @@
IMP ruby_imp = node == NULL ? imp : node->ruby_imp;
define_method:
- char *types;
Method method = class_getInstanceMethod(klass, sel);
- if (method != NULL) {
- types = (char *)method_getTypeEncoding(method);
- }
- else {
- // TODO look at informal protocols list
- types = (char *)alloca(oc_arity + 4);
- types[0] = '@';
- types[1] = '@';
- types[2] = ':';
- for (int i = 0; i < oc_arity; i++) {
- types[3 + i] = '@';
- }
- types[3 + oc_arity] = '\0';
- }
+ char types[100];
+ resolve_method_type(types, sizeof types, klass, method, sel, oc_arity);
+
GET_VM()->add_method(klass, sel, imp, ruby_imp, arity, flags, types);
if (!redefined) {
@@ -1661,7 +1667,8 @@
extern "C"
void
-rb_vm_define_method2(Class klass, SEL sel, rb_vm_method_node_t *node, bool direct)
+rb_vm_define_method2(Class klass, SEL sel, rb_vm_method_node_t *node,
+ bool direct)
{
assert(node != NULL);
@@ -2127,7 +2134,7 @@
static force_inline void
fill_ocache(struct mcache *cache, VALUE self, Class klass, IMP imp, SEL sel,
- int argc)
+ Method method, int argc)
{
cache->flag = MCACHE_OCALL;
ocache.klass = klass;
@@ -2135,7 +2142,7 @@
ocache.bs_method = GET_VM()->find_bs_method(klass, sel);
char types[200];
- if (!rb_objc_get_types(self, klass, sel, ocache.bs_method,
+ if (!rb_objc_get_types(self, klass, sel, method, ocache.bs_method,
types, sizeof types)) {
printf("cannot get encoding types for %c[%s %s]\n",
class_isMetaClass(klass) ? '+' : '-',
@@ -2184,7 +2191,7 @@
}
else {
// objc call
- fill_ocache(cache, self, klass, imp, sel, argc);
+ fill_ocache(cache, self, klass, imp, sel, method, argc);
}
}
else {
@@ -2941,11 +2948,12 @@
oklass = k;
}
+ Method method = class_getInstanceMethod((Class)klass, sel);
+ assert(method != NULL);
+
int arity;
if (node == NULL) {
- Method m = class_getInstanceMethod((Class)klass, sel);
- assert(m != NULL);
- arity = method_getNumberOfArguments(m) - 2;
+ arity = method_getNumberOfArguments(method) - 2;
}
else {
arity = node->arity.min;
@@ -2967,7 +2975,7 @@
// point to the method it was created from.
struct mcache *c = (struct mcache *)xmalloc(sizeof(struct mcache));
if (node == NULL) {
- fill_ocache(c, obj, oklass, imp, sel, arity);
+ fill_ocache(c, obj, oklass, imp, sel, method, arity);
}
else {
rb_vm_method_node_t *node = GET_VM()->method_node_get(imp);
Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h 2009-05-28 08:06:03 UTC (rev 1622)
+++ MacRuby/branches/experimental/vm.h 2009-05-28 20:38:09 UTC (rev 1623)
@@ -519,6 +519,8 @@
std::map<std::string, std::map<SEL, bs_element_method_t *> *>
bs_classes_class_methods, bs_classes_instance_methods;
std::map<std::string, bs_element_cftype_t *> bs_cftypes;
+ std::map<SEL, std::string> bs_informal_protocol_imethods,
+ bs_informal_protocol_cmethods;
bs_element_method_t *find_bs_method(Class klass, SEL sel);
rb_vm_bs_boxed_t *find_bs_boxed(std::string type);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090528/df4a7b34/attachment-0001.html>
More information about the macruby-changes
mailing list