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

source_changes at macosforge.org source_changes at macosforge.org
Tue Apr 21 17:06:53 PDT 2009


Revision: 1438
          http://trac.macosforge.org/projects/ruby/changeset/1438
Author:   lsansonetti at apple.com
Date:     2009-04-21 17:06:53 -0700 (Tue, 21 Apr 2009)
Log Message:
-----------
some work on incoming c/objc arguments

Modified Paths:
--------------
    MacRuby/branches/experimental/roxor.cpp
    MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.bridgesupport
    MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.m
    MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-04-21 21:10:07 UTC (rev 1437)
+++ MacRuby/branches/experimental/roxor.cpp	2009-04-22 00:06:53 UTC (rev 1438)
@@ -4849,17 +4849,35 @@
 
 extern "C"
 void
-rb_vm_rval_to_ocval(VALUE val, void **ocval)
+rb_vm_rval_to_ocval(VALUE rval, id *ocval)
 {
-    *(id *)ocval = val == Qnil ? NULL : RB2OC(val);
+    *ocval = rval == Qnil ? NULL : RB2OC(rval);
 }
 
 extern "C"
 void
-rb_vm_rval_to_ocsel(VALUE rval, void **ocval)
+rb_vm_rval_to_bool(VALUE rval, BOOL *ocval)
 {
+    switch (TYPE(rval)) {
+	case T_FALSE:
+	case T_NIL:
+	    *ocval = NO;
+	    break;
+
+	default:
+	    // All other types should be converted as true, to follow the Ruby
+	    // semantics (where for example any integer is always true, even 0).
+	    *ocval = YES;
+	    break;
+    }
+}
+
+extern "C"
+void
+rb_vm_rval_to_ocsel(VALUE rval, SEL *ocval)
+{
     if (NIL_P(rval)) {
-	*(SEL *)ocval = NULL;
+	*ocval = NULL;
     }
     else {
 	const char *cstr;
@@ -4876,12 +4894,125 @@
 	    default:
 		convert_error(_C_SEL, rval);
 	}
-	*(SEL *)ocval = sel_registerName(cstr);
+	*ocval = sel_registerName(cstr);
     }
 }
 
+static inline long
+rval_to_long(VALUE rval)
+{
+   return NUM2LONG(rb_Integer(rval)); 
+}
+
+static inline long long
+rval_to_long_long(VALUE rval)
+{
+    return NUM2LL(rb_Integer(rval));
+}
+
+static inline double
+rval_to_double(VALUE rval)
+{
+    return RFLOAT_VALUE(rb_Float(rval));
+}
+
+extern "C"
+void
+rb_vm_rval_to_chr(VALUE rval, char *ocval)
+{
+    if (TYPE(rval) == T_STRING && RSTRING_LEN(rval) == 1) {
+	*ocval = (char)RSTRING_PTR(rval)[0];
+    }
+    else {
+	*ocval = (char)rval_to_long(rval);
+    }
+}
+
+extern "C"
+void
+rb_vm_rval_to_uchr(VALUE rval, unsigned char *ocval)
+{
+    if (TYPE(rval) == T_STRING && RSTRING_LEN(rval) == 1) {
+	*ocval = (unsigned char)RSTRING_PTR(rval)[0];
+    }
+    else {
+	*ocval = (unsigned char)rval_to_long(rval);
+    }
+}
+
+extern "C"
+void
+rb_vm_rval_to_short(VALUE rval, short *ocval)
+{
+    *ocval = (short)rval_to_long(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_ushort(VALUE rval, unsigned short *ocval)
+{
+    *ocval = (unsigned short)rval_to_long(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_int(VALUE rval, int *ocval)
+{
+    *ocval = (int)rval_to_long(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_uint(VALUE rval, unsigned int *ocval)
+{
+    *ocval = (unsigned int)rval_to_long(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_long(VALUE rval, long *ocval)
+{
+    *ocval = (long)rval_to_long(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_ulong(VALUE rval, unsigned long *ocval)
+{
+    *ocval = (unsigned long)rval_to_long(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_long_long(VALUE rval, long long *ocval)
+{
+    *ocval = (long long)rval_to_long_long(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_ulong_long(VALUE rval, unsigned long long *ocval)
+{
+    *ocval = (unsigned long long)rval_to_long_long(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_double(VALUE rval, double *ocval)
+{
+    *ocval = (double)rval_to_double(rval);
+}
+
+extern "C"
+void
+rb_vm_rval_to_float(VALUE rval, float *ocval)
+{
+    *ocval = (float)rval_to_double(rval);
+}
+
 Value *
-RoxorCompiler::compile_conversion_to_c(const char *type, Value *val, Value *slot)
+RoxorCompiler::compile_conversion_to_c(const char *type, Value *val,
+				       Value *slot)
 {
     const char *func_name = NULL;
 
@@ -4891,6 +5022,58 @@
 	    func_name = "rb_vm_rval_to_ocval";
 	    break;
 
+	case _C_BOOL:
+	    func_name = "rb_vm_rval_to_bool";
+	    break;
+
+	case _C_CHR:
+	    func_name = "rb_vm_rval_to_chr";
+	    break;
+
+	case _C_UCHR:
+	    func_name = "rb_vm_rval_to_uchr";
+	    break;
+
+	case _C_SHT:
+	    func_name = "rb_vm_rval_to_short";
+	    break;
+
+	case _C_USHT:
+	    func_name = "rb_vm_rval_to_ushort";
+	    break;
+
+	case _C_INT:
+	    func_name = "rb_vm_rval_to_int";
+	    break;
+
+	case _C_UINT:
+	    func_name = "rb_vm_rval_to_uint";
+	    break;
+
+	case _C_LNG:
+	    func_name = "rb_vm_rval_to_long";
+	    break;
+
+	case _C_ULNG:
+	    func_name = "rb_vm_rval_to_ulong";
+	    break;
+
+	case _C_LNG_LNG:
+	    func_name = "rb_vm_rval_to_long_long";
+	    break;
+
+	case _C_ULNG_LNG:
+	    func_name = "rb_vm_rval_to_ulong_long";
+	    break;
+
+	case _C_FLT:
+	    func_name = "rb_vm_rval_to_float";
+	    break;
+
+	case _C_DBL:
+	    func_name = "rb_vm_rval_to_double";
+	    break;
+
 	case _C_SEL:
 	    func_name = "rb_vm_rval_to_ocsel";
 	    break;
@@ -4948,6 +5131,13 @@
 
 extern "C"
 VALUE
+rb_vm_sel_to_rval(SEL sel)
+{
+    return sel == 0 ? Qnil : ID2SYM(rb_intern(sel_getName(sel)));
+}
+
+extern "C"
+VALUE
 rb_vm_new_struct(VALUE klass, int argc, ...)
 {
     assert(argc > 0);
@@ -5051,6 +5241,10 @@
 	    func_name = "rb_float_new";
 	    break;
 
+	case _C_SEL:
+	    func_name = "rb_vm_sel_to_rval";
+	    break;
+
 	case _C_STRUCT_B:
 	    rb_vm_bs_boxed_t *bs_boxed = GET_VM()->find_bs_struct(type);
 	    if (bs_boxed != NULL) {

Modified: MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.bridgesupport
===================================================================
--- MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.bridgesupport	2009-04-21 21:10:07 UTC (rev 1437)
+++ MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.bridgesupport	2009-04-22 00:06:53 UTC (rev 1438)
@@ -8,5 +8,11 @@
     <method selector='methodReturningNO'>
       <retval type='B'/>
     </method>
+    <method selector='methodAcceptingTrueBOOL:'>
+      <arg index='0' type='B'/>
+    </method>
+    <method selector='methodAcceptingFalseBOOL:'>
+      <arg index='0' type='B'/>
+    </method>
   </class>
 </signatures>

Modified: MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.m
===================================================================
--- MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.m	2009-04-21 21:10:07 UTC (rev 1437)
+++ MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.m	2009-04-22 00:06:53 UTC (rev 1438)
@@ -141,6 +141,16 @@
     return 3.1415;
 }
 
+- (SEL)methodReturningSEL
+{
+    return @selector(foo:with:with:);
+}
+
+- (SEL)methodReturningSEL2
+{
+    return 0;
+}
+
 - (NSPoint)methodReturningNSPoint
 {
     return NSMakePoint(1, 2);
@@ -161,6 +171,106 @@
     return NSMakeRange(0, 42);
 }
 
+- (BOOL)methodAcceptingSelf:(id)obj
+{
+    return obj == self;
+}
+
+- (BOOL)methodAcceptingSelfClass:(id)obj
+{
+    return obj == [self class];
+}
+
+- (BOOL)methodAcceptingNil:(id)obj
+{
+    return obj == nil;
+}
+
+- (BOOL)methodAcceptingTrue:(id)obj
+{
+    return obj == (id)kCFBooleanTrue;
+}
+
+- (BOOL)methodAcceptingFalse:(id)obj
+{
+    return obj == (id)kCFBooleanFalse;
+}
+
+- (BOOL)methodAcceptingFixnum:(id)obj
+{
+    return [obj intValue] == 42;
+}
+
+- (BOOL)methodAcceptingChar:(char)c
+{
+    return c == 42;
+}
+
+- (BOOL)methodAcceptingUnsignedChar:(unsigned char)c
+{
+    return c == 42;
+}
+
+- (BOOL)methodAcceptingShort:(short)c
+{
+    return c == 42;
+}
+
+- (BOOL)methodAcceptingUnsignedShort:(unsigned short)c
+{
+    return c == 42;
+}
+
+- (BOOL)methodAcceptingInt:(int)c
+{
+    return c == 42;
+}
+
+- (BOOL)methodAcceptingUnsignedInt:(unsigned int)c
+{
+    return c == 42;
+}
+
+- (BOOL)methodAcceptingLong:(long)c
+{
+    return c == 42;
+}
+
+- (BOOL)methodAcceptingUnsignedLong:(unsigned long)c
+{
+    return c == 42;
+}
+
+- (BOOL)methodAcceptingTrueBOOL:(BOOL)b
+{
+    return b == YES;
+}
+
+- (BOOL)methodAcceptingFalseBOOL:(BOOL)b
+{
+    return b == NO;
+}
+
+- (BOOL)methodAcceptingSEL:(SEL)sel
+{
+    return sel == @selector(foo:with:with:);
+}
+
+- (BOOL)methodAcceptingSEL2:(SEL)sel
+{
+    return sel == 0;
+}
+
+- (BOOL)methodAcceptingFloat:(float)f
+{
+    return f > 3.1414 && f < 3.1416;
+}
+
+- (BOOL)methodAcceptingDouble:(double)d
+{
+    return d > 3.1414 && d < 3.1416;
+}
+
 @end
 
 void

Modified: MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb
===================================================================
--- MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb	2009-04-21 21:10:07 UTC (rev 1437)
+++ MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb	2009-04-22 00:06:53 UTC (rev 1438)
@@ -182,46 +182,35 @@
     o.methodReturningNO.should == false
   end
 
-  it "returning 'char' returns a Fixnum in Ruby" do
+  it "returning 'char' or 'unsigned char' returns a Fixnum in Ruby" do
     o = TestMethod.new
     o.methodReturningChar.should == 42
     o.methodReturningChar2.should == -42
+    o.methodReturningUnsignedChar.should == 42
   end
  
-  it "returning 'unsigned char' returns a Fixnum in Ruby" do
+  it "returning 'short' or 'unsigned short' returns a Fixnum in Ruby" do
     o = TestMethod.new
-    o.methodReturningUnsignedChar.should == 42
-  end
-
-  it "returning 'short' returns a Fixnum in Ruby" do
-    o = TestMethod.new
     o.methodReturningShort.should == 42
     o.methodReturningShort2.should == -42
-  end
-
-  it "returning 'unsigned short' returns a Fixnum in Ruby" do
-    o = TestMethod.new
     o.methodReturningUnsignedShort.should == 42
   end
 
-  it "returning 'int' returns a Fixnum in Ruby" do
+  it "returning 'int' or 'unsigned int' returns a Fixnum in Ruby" do
     o = TestMethod.new
     o.methodReturningInt.should == 42
     o.methodReturningInt2.should == -42
-  end
-
-  it "returning 'unsigned int' returns a Fixnum in Ruby" do
-    o = TestMethod.new
     o.methodReturningUnsignedInt.should == 42
   end
 
-  it "returning 'long' returns a Fixnum if possible in Ruby" do
+  it "returning 'long' or 'unsigned long' returns a Fixnum if possible in Ruby" do
     o = TestMethod.new
     o.methodReturningLong.should == 42
     o.methodReturningLong2.should == -42
+    o.methodReturningUnsignedLong.should == 42
   end
 
-  it "returning 'long' returns a Bignum if it cannot fix in a Fixnum in Ruby" do
+  it "returning 'long' or 'unsigned long' returns a Bignum if it cannot fix in a Fixnum in Ruby" do
     o = TestMethod.new
     o.methodReturningLong3.should ==
       (RUBY_ARCH == 'x86_64' ? 4611686018427387904 : 1073741824)
@@ -229,15 +218,6 @@
     o.methodReturningLong4.should ==
       (RUBY_ARCH == 'x86_64' ? -4611686018427387905 : -1073741825)
     o.methodReturningLong4.class.should == Bignum
-  end
-
-  it "returning 'unsigned long' returns a Fixnum if possible in Ruby" do
-    o = TestMethod.new
-    o.methodReturningUnsignedLong.should == 42
-  end
-
-  it "returning 'unsigned long' returns a Bignum if it cannot fix in a Fixnum in Ruby" do
-    o = TestMethod.new
     o.methodReturningUnsignedLong2.should ==
       (RUBY_ARCH == 'x86_64' ? 4611686018427387904 : 1073741824)
     o.methodReturningUnsignedLong2.class.should == Bignum
@@ -255,6 +235,14 @@
     o.methodReturningDouble.class.should == Float
   end
 
+  it "returning 'SEL' returns a Symbol or nil in Ruby" do
+    o = TestMethod.new
+    o.methodReturningSEL.class.should == Symbol
+    o.methodReturningSEL.should == :'foo:with:with:'
+    o.methodReturningSEL2.class.should == NilClass
+    o.methodReturningSEL2.should == nil
+  end
+
   it "returning 'NSPoint' returns an NSPoint boxed object in Ruby" do
     o = TestMethod.new
     b = o.methodReturningNSPoint
@@ -296,4 +284,130 @@
     b.length.class.should == Fixnum
     b.length.should == 42
   end
+
+  it "accepting the receiver as 'id' should receive the exact same object" do
+    o = TestMethod.new
+    o.methodAcceptingSelf(o).should == 1
+  end
+
+  it "accepting the receiver's class as 'id' should receive the exact same object" do
+    o = TestMethod.new
+    o.methodAcceptingSelfClass(o.class).should == 1
+  end
+
+  it "accepting 'nil' as 'id' should receive Objective-C's nil" do
+    o = TestMethod.new
+    o.methodAcceptingNil(nil).should == 1
+  end
+
+  it "accepting 'true' as 'id; should receive CF's kCFBooleanTrue" do
+    o = TestMethod.new
+    o.methodAcceptingTrue(true).should == 1
+  end
+
+  it "accepting 'false' as 'id' should receive CF's kCFBooleanFalse" do
+    o = TestMethod.new
+    o.methodAcceptingFalse(false).should == 1
+  end
+
+  it "accepting a Fixnum as 'id' should receive a Fixnum boxed object" do
+    o = TestMethod.new
+    o.methodAcceptingFixnum(42).should == 1
+  end
+
+  it "accepting nil or false as 'BOOL' should receive NO, any other object should receive YES" do
+    o = TestMethod.new
+    o.methodAcceptingFalseBOOL(nil).should == 1
+    o.methodAcceptingFalseBOOL(false).should == 1
+
+    o.methodAcceptingTrueBOOL(true).should == 1
+    o.methodAcceptingTrueBOOL(0).should == 1
+    o.methodAcceptingTrueBOOL(123).should == 1
+    o.methodAcceptingTrueBOOL('foo').should == 1
+    o.methodAcceptingTrueBOOL(Object.new).should == 1
+  end
+
+  it "accepting a Fixnum-compatible object as 'char', 'unsigned char', 'short', 'unsigned short', 'int', 'unsigned int', 'long', 'unsigned long' should receive the converted data, or raise an exception" do
+    o = TestMethod.new
+    o.methodAcceptingChar(42).should == 1
+    o.methodAcceptingUnsignedChar(42).should == 1
+    o.methodAcceptingShort(42).should == 1
+    o.methodAcceptingUnsignedShort(42).should == 1
+    o.methodAcceptingInt(42).should == 1
+    o.methodAcceptingUnsignedInt(42).should == 1
+    o.methodAcceptingLong(42).should == 1
+    o.methodAcceptingUnsignedLong(42).should == 1
+
+    o.methodAcceptingChar(42.0).should == 1
+    o.methodAcceptingUnsignedChar(42.0).should == 1
+    o.methodAcceptingShort(42.0).should == 1
+    o.methodAcceptingUnsignedShort(42.0).should == 1
+    o.methodAcceptingInt(42.0).should == 1
+    o.methodAcceptingUnsignedInt(42.0).should == 1
+    o.methodAcceptingLong(42.0).should == 1
+    o.methodAcceptingUnsignedLong(42.0).should == 1
+
+    o2 = Object.new
+    def o2.to_i; 42; end
+
+    o.methodAcceptingChar(o2).should == 1
+    o.methodAcceptingUnsignedChar(o2).should == 1
+    o.methodAcceptingShort(o2).should == 1
+    o.methodAcceptingUnsignedShort(o2).should == 1
+    o.methodAcceptingInt(o2).should == 1
+    o.methodAcceptingUnsignedInt(o2).should == 1
+    o.methodAcceptingLong(o2).should == 1
+    o.methodAcceptingUnsignedLong(o2).should == 1
+
+    lambda { o.methodAcceptingChar(nil) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingUnsignedChar(nil) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingShort(nil) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingUnsignedShort(nil) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingInt(nil) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingUnsignedInt(nil) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingLong(nil) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingUnsignedLong(nil) }.should raise_error(TypeError)
+
+    lambda { o.methodAcceptingChar(Object.new) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingUnsignedChar(Object.new) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingShort(Object.new) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingUnsignedShort(Object.new) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingInt(Object.new) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingUnsignedInt(Object.new) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingLong(Object.new) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingUnsignedLong(Object.new) }.should raise_error(TypeError)
+  end
+
+  it "accepting a one-character string as 'char' or 'unsigned char' should receive the first character" do
+    o = TestMethod.new
+    o.methodAcceptingChar('*').should == 1
+    o.methodAcceptingUnsignedChar('*').should == 1
+  end
+
+  it "accepting a String, Symbol or nil as 'SEL' should receive the appropriate selector" do
+    o = TestMethod.new
+    o.methodAcceptingSEL(:'foo:with:with:').should == 1
+    o.methodAcceptingSEL('foo:with:with:').should == 1
+    o.methodAcceptingSEL2(nil).should == 1
+
+    lambda { o.methodAcceptingSEL(123) }.should raise_error(TypeError)
+    lambda { o.methodAcceptingSEL(Object.new) }.should raise_error(TypeError)
+  end
+
+  it "accepting a Float-compatible object as 'float' or 'double' should receive the appropriate data" do
+    o = TestMethod.new
+    o.methodAcceptingFloat(3.1415).should == 1 
+    o.methodAcceptingDouble(3.1415).should == 1
+
+    o2 = Object.new
+    def o2.to_f; 3.1415; end
+
+    o.methodAcceptingFloat(o2).should == 1 
+    o.methodAcceptingDouble(o2).should == 1
+
+    lambda { o.methodAcceptingFloat(nil) }.should raise_error(TypeError) 
+    lambda { o.methodAcceptingDouble(nil) }.should raise_error(TypeError) 
+    lambda { o.methodAcceptingFloat(Object.new) }.should raise_error(TypeError) 
+    lambda { o.methodAcceptingDouble(Object.new) }.should raise_error(TypeError) 
+  end
 end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090421/14bfc847/attachment-0001.html>


More information about the macruby-changes mailing list