Skip to content

Commit

Permalink
- Fixes #531 by implementing #[] and #[]= as shortcuts for objectFor…
Browse files Browse the repository at this point in the history
…Key: and setObject:forKey:

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@3244 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
Thibault Martin-Lagardette committed Jan 11, 2010
1 parent f4495e0 commit 420a9db
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 3 deletions.
24 changes: 21 additions & 3 deletions dispatcher.cpp
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions id.c
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions id.h
Expand Up @@ -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;
Expand Down
26 changes: 26 additions & 0 deletions spec/macruby/fixtures/method.m
Expand Up @@ -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;
Expand All @@ -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
{
}
Expand Down
13 changes: 13 additions & 0 deletions spec/macruby/fixtures/method.rb
Expand Up @@ -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.