Skip to content
Browse files

- Fixes #531 by implementing #[] and #[]= as shortcuts for objectFor…

…Key: and setObject:forKey:

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@3244 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
1 parent f4495e0 commit 420a9dbbfc45f63e34573c1d91eee71abc75ba9f Thibault Martin-Lagardette committed
Showing with 64 additions and 3 deletions.
  1. +21 −3 dispatcher.cpp
  2. +2 −0 id.c
  3. +2 −0 id.h
  4. +26 −0 spec/macruby/fixtures/method.m
  5. +13 −0 spec/macruby/fixtures/method.rb
View
24 dispatcher.cpp
@@ -202,6 +202,12 @@ helper_sel(const char *p, size_t len)
buf[len + 1] = '\0';
new_sel = sel_registerName(buf);
}
+ else if (strcmp(p, "[]:") == 0) {
+ new_sel = selObjectForKey;
+ }
+ else if (strcmp(p, "[]=:") == 0) {
+ new_sel = selSetObjectForKey;
+ }
return new_sel;
}
@@ -566,7 +572,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self,
#if ROXOR_VM_DEBUG
bool cached = true;
#endif
- bool do_rcache = true;
+ bool cache_method = true;
if (cache->flag == 0) {
recache:
@@ -650,7 +656,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self,
Method m = class_getInstanceMethod(klass, sel);
if (m != NULL) {
method = m;
- do_rcache = false;
+ cache_method = false;
goto recache2;
}
}
@@ -665,6 +671,15 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self,
if (GET_CORE()->method_node_get(m) == NULL) {
sel = new_sel;
method = m;
+ // We need to invert arguments because
+ // #[]= and setObject:forKey: take arguments
+ // in a reverse order
+ if (new_sel == selSetObjectForKey && argc == 2) {
+ VALUE swap = argv[0];
+ ((VALUE *)argv)[0] = argv[1];
+ ((VALUE *)argv)[1] = swap;
+ cache_method = false;
+ }
goto recache2;
}
}
@@ -699,7 +714,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self,
if (rcache.klass != klass) {
goto recache;
}
- if (!do_rcache) {
+ if (!cache_method) {
cache->flag = 0;
}
@@ -773,6 +788,9 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self,
if (ocache.klass != klass) {
goto recache;
}
+ if (!cache_method) {
+ cache->flag = 0;
+ }
if (block != NULL) {
if (self == rb_cNSMutableHash && sel == selNew) {
View
2 id.c
@@ -105,6 +105,8 @@ Init_id(void)
selWrite = sel_registerName("write:");
selInherited = sel_registerName("inherited:");
selLambda = sel_registerName("lambda");
+ selObjectForKey = sel_registerName("objectForKey:");
+ selSetObjectForKey = sel_registerName("setObject:forKey:");
cacheEach = rb_vm_get_call_cache(selEach);
#endif
View
2 id.h
@@ -114,6 +114,8 @@ extern SEL selIsEqual;
extern SEL selWrite;
extern SEL selInherited;
extern SEL selLambda;
+extern SEL selObjectForKey;
+extern SEL selSetObjectForKey;
extern ID idIncludedModules;
extern ID idIncludedInClasses;
extern ID idAncestors;
View
26 spec/macruby/fixtures/method.m
@@ -10,11 +10,27 @@ - (BOOL)informalProtocolMethod2:(int)arg1 withValue:(int)arg2;
@interface TestMethod : NSObject
{
id _foo;
+ NSMutableDictionary *dic;
}
@end
@implementation TestMethod
+- (id)init
+{
+ if (self = [super init])
+ {
+ dic = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [dic release];
+ [super dealloc];
+}
+
- (BOOL)isFoo
{
return YES;
@@ -35,6 +51,16 @@ - (id)foo
return _foo;
}
+- (void)setObject:(id)obj forKey:(NSString *)key
+{
+ [dic setObject:obj forKey:key];
+}
+
+- (id)objectForKey:(NSString *)key
+{
+ return [dic objectForKey:key];
+}
+
- (void)methodReturningVoid
{
}
View
13 spec/macruby/fixtures/method.rb
@@ -69,3 +69,16 @@ def informalProtocolMethod2(x, withValue:x2)
x + x2 == 42
end
end
+
+require File.dirname(__FILE__) + "/../spec_helper"
+
+describe "An Obj-C object" do
+ before :each do
+ @o = TestMethod.new
+ end
+
+ it "allows the use of #[] and #[]= as respective shortcuts to objectForKey: and setObject:forKey:" do
+ @o['foo'] = 'ok'
+ @o['foo'].should == 'ok'
+ end
+end

0 comments on commit 420a9db

Please sign in to comment.
Something went wrong with that request. Please try again.