[macruby-changes] [4066] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Mon May 10 19:28:32 PDT 2010
Revision: 4066
http://trac.macosforge.org/projects/ruby/changeset/4066
Author: martinlagardette at apple.com
Date: 2010-05-10 19:28:27 -0700 (Mon, 10 May 2010)
Log Message:
-----------
Improve core/array pass rate
- Implement #rotate, #rotate!, #select!, #keep_if, #sort_by!
- Fix various bugs to comply with the specs
- Delete now-working specs
Modified Paths:
--------------
MacRuby/trunk/NSArray.m
MacRuby/trunk/array.c
MacRuby/trunk/spec/frozen/tags/macruby/core/array/join_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/array/multiply_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/array/sort_by_tags.txt
Removed Paths:
-------------
MacRuby/trunk/spec/frozen/tags/macruby/core/array/flatten_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/array/keep_if_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/array/rotate_tags.txt
MacRuby/trunk/spec/frozen/tags/macruby/core/array/select_tags.txt
Modified: MacRuby/trunk/NSArray.m
===================================================================
--- MacRuby/trunk/NSArray.m 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/NSArray.m 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1141,7 +1141,7 @@
{
VALUE *arg = (VALUE *)argp;
if (recur) {
- return rb_usascii_str_new2("[...]");
+ rb_raise(rb_eArgError, "recursive array join");
}
return rb_ary_join(arg[0], arg[1]);
}
Modified: MacRuby/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/array.c 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1340,6 +1340,111 @@
return rary_reverse_bang(rary_dup(ary, 0), 0);
}
+static inline long
+rotate_count(long cnt, long len)
+{
+ return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
+}
+
+static void
+ary_reverse(VALUE ary, long pos1, long pos2)
+{
+ while (pos1 < pos2) {
+ VALUE elem = rary_elt(ary, pos1);
+ rary_elt_set(ary, pos1, rary_elt(ary, pos2));
+ rary_elt_set(ary, pos2, elem);
+ pos1++;
+ pos2--;
+ }
+}
+
+VALUE
+ary_rotate(VALUE ary, long cnt)
+{
+ rb_ary_modify(ary);
+ if (cnt != 0) {
+ long len = RARY(ary)->len;
+ if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
+ --len;
+ if (cnt < len) {
+ ary_reverse(ary, cnt, len);
+ }
+ if (--cnt > 0) {
+ ary_reverse(ary, 0, cnt);
+ }
+ if (len > 0) {
+ ary_reverse(ary, 0, len);
+ }
+ return ary;
+ }
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * array.rotate!([cnt = 1]) -> array
+ *
+ * Rotates _self_ in place so that the element at +cnt+ comes first,
+ * and returns _self_. If +cnt+ is negative then it rotates in
+ * counter direction.
+ *
+ * a = [ "a", "b", "c", "d" ]
+ * a.rotate! #=> ["b", "c", "d", "a"]
+ * a #=> ["b", "c", "d", "a"]
+ * a.rotate!(2) #=> ["d", "a", "b", "c"]
+ * a.rotate!(-3) #=> ["a", "b", "c", "d"]
+ */
+
+static VALUE
+rary_rotate_bang(VALUE ary, SEL sel, int argc, VALUE *argv)
+{
+ VALUE n;
+ long cnt = 1;
+
+ rb_scan_args(argc, argv, "01", &n);
+ if (!NIL_P(n)) {
+ cnt = NUM2LONG(n);
+ }
+ ary_rotate(ary, cnt);
+ return ary;
+}
+
+/*
+ * call-seq:
+ * array.rotate([n = 1]) -> an_array
+ *
+ * Returns new array by rotating _self_, whose first element is the
+ * element at +cnt+ in _self_. If +cnt+ is negative then it rotates
+ * in counter direction.
+ *
+ * a = [ "a", "b", "c", "d" ]
+ * a.rotate #=> ["b", "c", "d", "a"]
+ * a #=> ["a", "b", "c", "d"]
+ * a.rotate(2) #=> ["c", "d", "a", "b"]
+ * a.rotate(-3) #=> ["b", "c", "d", "a"]
+ */
+
+static VALUE
+rary_rotate(VALUE ary, SEL sel, int argc, VALUE *argv)
+{
+ VALUE rotated;
+ VALUE n;
+ long cnt = 1;
+
+ rb_scan_args(argc, argv, "01", &n);
+ if (!NIL_P(n)) {
+ cnt = NUM2LONG(n);
+ }
+
+ rotated = rary_dup(ary, 0);
+ if (RARY(ary)->len > 0) {
+ ary_rotate(rotated, cnt);
+ }
+ return rotated;
+}
+
static int
sort_1(void *dummy, const void *ap, const void *bp)
{
@@ -1474,6 +1579,33 @@
return sort_bang(ary, true);
}
+static VALUE
+sort_by_i(VALUE i)
+{
+ return rb_yield(i);
+}
+
+/*
+ * call-seq:
+ * array.sort_by! {| obj | block } -> array
+ *
+ * Sorts <i>array</i> in place using a set of keys generated by mapping the
+ * values in <i>array</i> through the given block.
+ */
+
+static VALUE
+rary_sort_by_bang(VALUE ary, SEL sel)
+{
+ VALUE sorted;
+
+ RETURN_ENUMERATOR(ary, 0, 0);
+ rb_ary_modify(ary);
+ sorted = rb_objc_block_call(ary, sel_registerName("sort_by"), NULL, 0, 0,
+ sort_by_i, 0);
+ rb_ary_replace(ary, sorted);
+ return ary;
+}
+
/*
* call-seq:
* array.collect! {|item| block } -> array
@@ -1613,6 +1745,64 @@
/*
* call-seq:
+ * array.select! {|item| block } -> an_array
+ *
+ * Invokes the block passing in successive elements from
+ * <i>array</i>, deleting elements for which the block returns a
+ * false value. but returns <code>nil</code> if no changes were
+ * made. Also see <code>Array#keep_if</code>
+ */
+
+static VALUE
+rary_select_bang(VALUE ary, SEL sel)
+{
+ long i1, i2;
+
+ RETURN_ENUMERATOR(ary, 0, 0);
+ rb_ary_modify(ary);
+ for (i1 = i2 = 0; i1 < RARY(ary)->len; i1++) {
+ VALUE v = rary_elt(ary, i1);
+ VALUE test = RTEST(rb_yield(v));
+ RETURN_IF_BROKEN();
+ if (!RTEST(test)) {
+ continue;
+ }
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, v);
+ }
+ i2++;
+ }
+
+ if (RARY(ary)->len == i2) {
+ return Qnil;
+ }
+ if (i2 < RARY(ary)->len) {
+ RARY(ary)->len = i2;
+ }
+ return ary;
+}
+
+/*
+ * call-seq:
+ * array.keep_if {|item| block } -> an_array
+ *
+ * Deletes every element of <i>self</i> for which <i>block</i> evaluates
+ * to <code>false</code>.
+ *
+ * a = %w{ a b c d e f }
+ * a.keep_if {|v| v =~ /[aeiou]/} #=> ["a", "e"]
+ */
+
+static VALUE
+rary_keep_if(VALUE ary, SEL sel)
+{
+ RETURN_ENUMERATOR(ary, 0, 0);
+ rary_select_bang(ary, 0);
+ return ary;
+}
+
+/*
+ * call-seq:
* array.delete(obj) -> obj or nil
* array.delete(obj) { block } -> obj or nil
*
@@ -1746,15 +1936,24 @@
pos = NUM2LONG(arg1);
len = NUM2LONG(arg2);
delete_pos_len:
+ if (len < 0) {
+ return Qnil;
+ }
if (pos < 0) {
pos = alen + pos;
if (pos < 0) {
return Qnil;
}
}
+ else if (alen < pos) {
+ return Qnil;
+ }
if (alen < len || alen < pos + len) {
len = alen - pos;
}
+ if (len == 0) {
+ return rb_ary_new2(0);
+ }
arg2 = rary_subseq(ary, pos, len);
rary_splice(ary, pos, len, Qundef);
return arg2;
@@ -2783,7 +2982,7 @@
level = NUM2INT(lv);
}
if (level == 0) {
- return ary;
+ return Qnil;
}
result = flatten(ary, level, &mod);
@@ -2825,7 +3024,7 @@
level = NUM2INT(lv);
}
if (level == 0) {
- return ary;
+ return rary_dup(ary, 0);
}
result = flatten(ary, level, &mod);
@@ -3525,13 +3724,18 @@
rb_objc_define_method(rb_cRubyArray, "rindex", rary_rindex, -1);
rb_objc_define_method(rb_cRubyArray, "reverse", rary_reverse, 0);
rb_objc_define_method(rb_cRubyArray, "reverse!", rary_reverse_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "rotate", rary_rotate, -1);
+ rb_objc_define_method(rb_cRubyArray, "rotate!", rary_rotate_bang, -1);
rb_objc_define_method(rb_cRubyArray, "sort", rary_sort, 0);
rb_objc_define_method(rb_cRubyArray, "sort!", rary_sort_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "sort_by!", rary_sort_by_bang, 0);
rb_objc_define_method(rb_cRubyArray, "collect", rary_collect, 0);
rb_objc_define_method(rb_cRubyArray, "collect!", rary_collect_bang, 0);
rb_objc_define_method(rb_cRubyArray, "map", rary_collect, 0);
rb_objc_define_method(rb_cRubyArray, "map!", rary_collect_bang, 0);
rb_objc_define_method(rb_cRubyArray, "select", rary_select, 0);
+ rb_objc_define_method(rb_cRubyArray, "select!", rary_select_bang, 0);
+ rb_objc_define_method(rb_cRubyArray, "keep_if", rary_keep_if, 0);
rb_objc_define_method(rb_cRubyArray, "values_at", rary_values_at, -1);
rb_objc_define_method(rb_cRubyArray, "delete", rary_delete, 1);
rb_objc_define_method(rb_cRubyArray, "delete_at", rary_delete_at, 1);
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/array/flatten_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/flatten_tags.txt 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/flatten_tags.txt 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1,2 +0,0 @@
-fails:Array#flatten! returns nil when the level of recursion is 0
-fails:Array#flatten returns dup when the level of recursion is 0
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/array/join_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/join_tags.txt 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/join_tags.txt 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1,2 +1 @@
-fails:Array#join raises an ArgumentError when the Array is recursive
fails:Array#join returns a string formed by concatenating each element.to_str separated by separator without trailing separator
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/array/keep_if_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/keep_if_tags.txt 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/keep_if_tags.txt 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1,3 +0,0 @@
-fails:Array#keep_if returns the same array if no changes were made
-fails:Array#keep_if deletes elements for which the block returns a false value
-fails:Array#keep_if returns an enumerator if no block is given
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/array/multiply_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/multiply_tags.txt 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/multiply_tags.txt 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1,2 +1 @@
-fails:Array#* with a string raises an ArgumentError when the Array is recursive
fails:Array#* with a string returns a string formed by concatenating each element.to_str separated by separator without trailing separator
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/array/rotate_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/rotate_tags.txt 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/rotate_tags.txt 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1,9 +0,0 @@
-fails:Array#rotate returns a copy of the array whose first n elements is moved to the last
-fails:Array#rotate returns a copy of the array when the length is one
-fails:Array#rotate returns an empty array when self is empty
-fails:Array#rotate does not return self
-fails:Array#rotate returns subclass instance for Array subclasses
-fails:Array#rotate! moves the first n elements to the last and returns self
-fails:Array#rotate! does nothing and returns self when the length is zero or one
-fails:Array#rotate! returns self
-fails:Array#rotate! raises a RuntimeError on a frozen array
Deleted: MacRuby/trunk/spec/frozen/tags/macruby/core/array/select_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/select_tags.txt 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/select_tags.txt 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1,3 +0,0 @@
-fails:Array#select! returns nil if no changes were made in the array
-fails:Array#select! deletes elements for which the block returns a false value
-fails:Array#select! returns an enumerator if no block is given
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/array/sort_by_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/array/sort_by_tags.txt 2010-05-11 02:06:36 UTC (rev 4065)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/array/sort_by_tags.txt 2010-05-11 02:28:27 UTC (rev 4066)
@@ -1,6 +1,2 @@
fails:Array#sort_by! sorts array in place by passing each element to the given block
-fails:Array#sort_by! returns an Enumerator if not given a block
-fails:Array#sort_by! completes when supplied a block that always returns the same result
-fails:Array#sort_by! raises a RuntimeError on a frozen array
fails:Array#sort_by! returns the specified value when it would break in the given block
-fails:Array#sort_by! makes some modification even if finished sorting when it would break in the given block
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100510/38c889b4/attachment-0001.html>
More information about the macruby-changes
mailing list