Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Array specs #52

Merged
merged 22 commits into from

2 participants

@gglresearchanddevelopment

Update IronRuby to pass more of rubyspec core/array specs

gglresearchanddevelopment and others added some commits
@gglresearchanddevelopment gglresearchanddevelopment Update implementation of Enumerable.zip to call .each on args if .to_…
…ary fails (as per rubyspec)
a3d5012
Orion Edwards [GGL] Update implementation of Array.uniq and uniq! to use blocks correctly…
… (as per rubyspec)

Bugfix uniq! when dealing with recursive arrays (as per rubyspec)
5a52d46
Orion Edwards [GGL] Update implementation of Array[]= to check frozen before coercing arg…
…s, and change the error message to match MRI 1.9.2 (as per rubyspec)
510023a
Orion Edwards [GGL] Update implementation of Array#fill to check frozen on empty array, a…
…nd do proper boundary checking (as per rubyspec)
ff5f4bf
Orion Edwards [GGL] Update implementation of Array.shuffle! to check frozen correctly (as…
… per rubyspec)
3ce9b1f
Orion Edwards [GGL] Implement Array#select! (as per rubyspec) 8208196
Orion Edwards [GGL] Update Array#shift to check for frozen correctly (as per rubyspec)
Implement Array#shift(n) (as per rubyspec)
7ded4c3
Orion Edwards [GGL] Implement Array#sample and Arran#sample(n) as per rubyspec f041d20
Orion Edwards [GGL] Implement Array#rotate and Array#rotate! as per rubyspec b687d8b
Orion Edwards [GGL] Implement Array#rindex when called with no args and no block (reverse…
… index-finding enumerator) as per rubyspec
62f936c
Orion Edwards [GGL] Array#pop should check frozen even when empty (as per rubyspec). Also…
… update other fixes to use existing implementation of RequireNotFrozen(IList) instead of manually casting
a1ec97c
Orion Edwards [GGL] #to_ary is allowed to return nil. Fixes Array#flatten as per rubyspec 411a3e5
Orion Edwards [GGL] Add range checking to Array#product so the tests no longer run out of…
… memory and hang (also part of rubyspec error checking)
3f5b7a6
Orion Edwards [GGL] Minor fixes:
- Some methods were declared as taking RubyArray parameters instead of IList
- One more instance of RequireNotFrozen
b3efe76
Orion Edwards [GGL] Minor fixes:
- Some methods were declared as taking RubyArray parameters instead of IList
- One more instance of RequireNotFrozen
b017689
Orion Edwards [GGL] Resolve merge conflict caused by accidental checkin of wrong initiali…
…zers.generated file
e83501a
Orion Edwards [GGL] Merge branch 'master' into array_specs adfd117
Orion Edwards [GGL] I was using ArrayList (which is not available in Silverlight) interna…
…lly Array#sample. Update to use List<object>
7975d9e
Orion Edwards [GGL] Update Array#slice! to deal with out-of-range values as per rubyspec ae966af
Orion Edwards [GGL] Update Array#inspect to taint result strings correctly as per rubyspec c89e236
Orion Edwards [GGL] Implement Array#keep_if as per rubyspec e92404b
Orion Edwards [GGL] Update Array#product to handle block parameters as per rubyspec ede005c
@tmat tmat merged commit ede005c into IronLanguages:master
@tmat
Owner

Merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 4, 2012
  1. @gglresearchanddevelopment
  2. Update implementation of Array.uniq and uniq! to use blocks correctly…

    Orion Edwards [GGL] authored
    … (as per rubyspec)
    
    Bugfix uniq! when dealing with recursive arrays (as per rubyspec)
  3. Update implementation of Array[]= to check frozen before coercing arg…

    Orion Edwards [GGL] authored
    …s, and change the error message to match MRI 1.9.2 (as per rubyspec)
  4. Update implementation of Array#fill to check frozen on empty array, a…

    Orion Edwards [GGL] authored
    …nd do proper boundary checking (as per rubyspec)
  5. Update implementation of Array.shuffle! to check frozen correctly (as…

    Orion Edwards [GGL] authored
    … per rubyspec)
  6. Implement Array#select! (as per rubyspec)

    Orion Edwards [GGL] authored
  7. Update Array#shift to check for frozen correctly (as per rubyspec)

    Orion Edwards [GGL] authored
    Implement Array#shift(n) (as per rubyspec)
  8. Implement Array#sample and Arran#sample(n) as per rubyspec

    Orion Edwards [GGL] authored
Commits on Jan 5, 2012
  1. Implement Array#rotate and Array#rotate! as per rubyspec

    Orion Edwards [GGL] authored
  2. Implement Array#rindex when called with no args and no block (reverse…

    Orion Edwards [GGL] authored
    … index-finding enumerator) as per rubyspec
  3. Array#pop should check frozen even when empty (as per rubyspec). Also…

    Orion Edwards [GGL] authored
    … update other fixes to use existing implementation of RequireNotFrozen(IList) instead of manually casting
  4. Add range checking to Array#product so the tests no longer run out of…

    Orion Edwards [GGL] authored
    … memory and hang (also part of rubyspec error checking)
Commits on Jan 6, 2012
  1. Minor fixes:

    Orion Edwards [GGL] authored
    - Some methods were declared as taking RubyArray parameters instead of IList
    - One more instance of RequireNotFrozen
  2. Minor fixes:

    Orion Edwards [GGL] authored
    - Some methods were declared as taking RubyArray parameters instead of IList
    - One more instance of RequireNotFrozen
  3. Resolve merge conflict caused by accidental checkin of wrong initiali…

    Orion Edwards [GGL] authored
    …zers.generated file
Commits on Jan 31, 2012
  1. Merge branch 'master' into array_specs

    Orion Edwards [GGL] authored
  2. I was using ArrayList (which is not available in Silverlight) interna…

    Orion Edwards [GGL] authored
    …lly Array#sample. Update to use List<object>
Commits on Feb 1, 2012
  1. Implement Array#keep_if as per rubyspec

    Orion Edwards [GGL] authored
  2. Update Array#product to handle block parameters as per rubyspec

    Orion Edwards [GGL] authored
This page is out of date. Refresh to see the latest.
View
21 Languages/Ruby/Libraries/Builtins/Enumerable.cs
@@ -681,16 +681,33 @@ public static class Enumerable {
#region zip
[RubyMethod("zip")]
- public static object Zip(CallSiteStorage<EachSite>/*!*/ each, BlockParam block, object self, [DefaultProtocol, NotNullItems]params IList/*!*/[]/*!*/ args) {
+ public static object Zip(CallSiteStorage<EachSite>/*!*/ each, ConversionStorage<IList>/*!*/ tryToAry, CallSiteStorage<EachSite>/*!*/ otherEach, BlockParam block, object self, [DefaultProtocol, NotNullItems] params object/*!*/[]/*!*/ args) {
RubyArray results = (block == null) ? new RubyArray() : null;
object result = results;
+ // coerce the args into arrays
+ var coercedArgs = new List<IList>(args.Length);
+ foreach (var otherArrayObject in args) {
+ IList otherArray = Protocols.TryCastToArray(tryToAry, otherArrayObject);
+ if (otherArray != null) {
+ coercedArgs.Add(otherArray);
+ } else { // added in MRI 1.9.2 - if to_ary fails, try call .each to extract values
+ otherArray = new List<object>();
+ Each(otherEach, otherArrayObject, Proc.Create(otherEach.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) {
+ otherArray.Add(item);
+ return null;
+ }));
+ coercedArgs.Add(otherArray);
+ }
+ }
+
+
int index = 0;
Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) {
// Collect items
RubyArray array = new RubyArray(args.Length + 1);
array.Add(item);
- foreach (IList otherArray in args) {
+ foreach (var otherArray in coercedArgs) {
if (index < otherArray.Count) {
array.Add(otherArray[index]);
} else {
View
341 Languages/Ruby/Libraries/Extensions/IListOps.cs
@@ -41,7 +41,7 @@ public static class IListOps {
private static void RequireNotFrozen(IList/*!*/ self) {
RubyArray array = self as RubyArray;
if (array != null && array.IsFrozen) {
- throw RubyExceptions.CreateObjectFrozenError();
+ throw RubyExceptions.CreateArrayFrozenError();
}
}
@@ -312,24 +312,43 @@ public static class IListOps {
}
[RubyMethod("product")]
- public static RubyArray/*!*/ Product(IList/*!*/ self, [DefaultProtocol, NotNullItems]params IList/*!*/[]/*!*/ arrays) {
+ public static IList/*!*/ Product(BlockParam block, IList/*!*/ self, [DefaultProtocol, NotNullItems]params IList/*!*/[]/*!*/ arrays) {
var result = new RubyArray();
+ object blockResult = null;
if (self.Count == 0) {
- return result;
+ return self;
}
+
+ int requiredCapacity = 1;
for (int i = 0; i < arrays.Length; i++) {
if (arrays[i].Count == 0) {
+ if (block != null) { // [1,2].product([]) should produce [], but [1,2].product([]){ } should produce [1,2] due to empty block
+ return self;
+ }
return result;
}
+ try {
+ requiredCapacity = checked(requiredCapacity * arrays[i].Count);
+ } catch (OverflowException) {
+ throw RubyExceptions.CreateRangeError("too big to product");
+ }
}
-
+
int[] indices = new int[1 + arrays.Length];
while (true) {
var current = new RubyArray(indices.Length);
for (int i = 0; i < indices.Length; i++) {
current[i] = GetNth(i, self, arrays)[indices[i]];
}
+
+ if (block != null) {
+ block.Yield(current, out blockResult);
+ if (blockResult == null) {
+ return self;
+ }
+ }
+
result.Add(current);
// increment indices:
@@ -519,7 +538,7 @@ public static class IListOps {
return self[index] = value;
}
-
+
[RubyMethod("[]=")]
public static object SetElement(IList/*!*/ self, [DefaultProtocol]int index, object value) {
index = NormalizeIndexThrowIfNegative(self, index);
@@ -534,11 +553,20 @@ public static class IListOps {
}
[RubyMethod("[]=")]
+ public static object SetElement(ConversionStorage<IList>/*!*/ arrayTryCast, ConversionStorage<int> fixnumCast,
+ IList/*!*/ self, object index, object length, object value) {
+
+ RequireNotFrozen(self); // rubyspec says we must check for frozen before trying to coerce the index
+ return SetElement(arrayTryCast, self as IList, Protocols.CastToFixnum(fixnumCast, index), Protocols.CastToFixnum(fixnumCast, length), value);
+ }
+
+ [RubyMethod("[]=")]
public static object SetElement(ConversionStorage<IList>/*!*/ arrayTryCast, IList/*!*/ self,
[DefaultProtocol]int index, [DefaultProtocol]int length, object value) {
if (length < 0) {
throw RubyExceptions.CreateIndexError("negative length ({0})", length);
}
+ RequireNotFrozen(self);
index = NormalizeIndexThrowIfNegative(self, index);
@@ -584,24 +612,36 @@ public static class IListOps {
[RubyMethod("[]=")]
public static object SetElement(ConversionStorage<IList>/*!*/ arrayTryCast, ConversionStorage<int>/*!*/ fixnumCast,
- IList/*!*/ self, [NotNull]Range/*!*/ range, object value) {
+ IList/*!*/ self, object rangeOrIndex, object value) {
+
+ RequireNotFrozen(self);
- int start, count;
- RangeToStartAndCount(fixnumCast, range, self.Count, out start, out count);
- return SetElement(arrayTryCast, self, start, count, value);
+ var range = rangeOrIndex as Range;
+ if (range == null) {
+ return SetElement(self, Protocols.CastToFixnum(fixnumCast, rangeOrIndex), value);
+ } else {
+ int start, count;
+ if (TryRangeToStartAndCount(fixnumCast, range, self.Count, out start, out count)) {
+ return SetElement(arrayTryCast, self, start, count, value);
+ } else {
+ throw RubyExceptions.CreateRangeError("{0} out of range", range);
+ }
+ }
}
- private static void RangeToStartAndCount(ConversionStorage<int>/*!*/ fixnumCast, Range/*!*/ range, int length, out int start, out int count) {
+ private static bool TryRangeToStartAndCount(ConversionStorage<int>/*!*/ fixnumCast, Range/*!*/ range, int length, out int start, out int count) {
start = Protocols.CastToFixnum(fixnumCast, range.Begin);
int end = Protocols.CastToFixnum(fixnumCast, range.End);
start = start < 0 ? start + length : start;
if (start < 0) {
- throw RubyExceptions.CreateRangeError("{0}..{1} out of range", start, end);
+ count = -1;
+ return false;
}
end = end < 0 ? end + length : end;
count = Math.Max(range.ExcludeEnd ? end - start : end - start + 1, 0);
+ return true;
}
#endregion
@@ -633,18 +673,23 @@ public static class IListOps {
return result;
}
- private static void AddUniqueItems(IList/*!*/ list, IList/*!*/ result, Dictionary<object, bool> seen, ref bool nilSeen) {
+ private static void AddUniqueItems(BlockParam block, IList/*!*/ list, IList/*!*/ result, Dictionary<object, bool> seen, ref bool nilSeen) {
foreach (object item in list) {
- if (item == null) {
+ object key;
+ if (block == null || block.Yield(item, out key)) {
+ key = item;
+ }
+
+ if (key == null) {
if (!nilSeen) {
nilSeen = true;
- result.Add(null);
+ result.Add(item);
}
continue;
}
- if (!seen.ContainsKey(item)) {
- seen.Add(item, true);
+ if (!seen.ContainsKey(key)) {
+ seen.Add(key, true);
result.Add(item);
}
}
@@ -658,9 +703,9 @@ public static class IListOps {
var result = new RubyArray();
// Union merges the two arrays, removing duplicates
- AddUniqueItems(self, result, seen, ref nilSeen);
+ AddUniqueItems(null, self, result, seen, ref nilSeen);
- AddUniqueItems(other, result, seen, ref nilSeen);
+ AddUniqueItems(null, other, result, seen, ref nilSeen);
return result;
}
@@ -749,7 +794,7 @@ public static class IListOps {
#endregion
- #region delete, delete_at, reject, reject!
+ #region delete, delete_at, reject, reject!, select!, keep_if
public static bool Remove(BinaryOpStorage/*!*/ equals, IList/*!*/ self, object item) {
int i = 0;
@@ -801,7 +846,7 @@ public static class IListOps {
private static object DeleteIfImpl(BlockParam/*!*/ block, IList/*!*/ self) {
bool changed, jumped;
- DeleteIf(block, self, out changed, out jumped);
+ DeleteIf(block, self, RubyOps.IsTrue, out changed, out jumped);
return self;
}
@@ -812,7 +857,7 @@ public static class IListOps {
private static object RejectInPlaceImpl(BlockParam/*!*/ block, IList/*!*/ self) {
bool changed, jumped;
- object result = DeleteIf(block, self, out changed, out jumped);
+ object result = DeleteIf(block, self, RubyOps.IsTrue, out changed, out jumped);
return jumped ? result : changed ? self : null;
}
@@ -842,7 +887,30 @@ public static class IListOps {
return result;
}
- private static object DeleteIf(BlockParam/*!*/ block, IList/*!*/ self, out bool changed, out bool jumped) {
+ [RubyMethod("select!")]
+ public static object SelectInPlace(BlockParam block, IList/*!*/ self) {
+ return (block != null) ? SelectInPlaceImpl(block, self) : new Enumerator((_, innerBlock) => SelectInPlaceImpl(innerBlock, self));
+ }
+
+ private static object SelectInPlaceImpl(BlockParam/*!*/ block, IList/*!*/ self) {
+ bool changed, jumped;
+ object result = DeleteIf(block, self, RubyOps.IsFalse, out changed, out jumped);
+ return jumped ? result : changed ? self : null;
+ }
+
+ [RubyMethod("keep_if")]
+ public static object KeepIf(BlockParam block, IList/*!*/ self) {
+ // as far as I can tell the only difference between select! and keep_if, is that keep_if returns self if it doesn't modify the array whereas select! returns nil
+ return (block != null) ? KeepIfImpl(block, self) : new Enumerator((_, innerBlock) => KeepIfImpl(innerBlock, self));
+ }
+
+ private static object KeepIfImpl(BlockParam/*!*/ block, IList/*!*/ self) {
+ bool changed, jumped;
+ object result = DeleteIf(block, self, RubyOps.IsFalse, out changed, out jumped);
+ return jumped ? result : self;
+ }
+
+ private static object DeleteIf(BlockParam/*!*/ block, IList/*!*/ self, Func<object, bool> predicate, out bool changed, out bool jumped) {
Assert.NotNull(block, self);
changed = false;
@@ -859,7 +927,7 @@ public static class IListOps {
return result;
}
- if (RubyOps.IsTrue(result)) {
+ if (predicate(result)) {
changed = true;
self.RemoveAt(i);
} else {
@@ -964,6 +1032,8 @@ public static class IListOps {
[RubyMethod("fill")]
public static IList/*!*/ Fill(IList/*!*/ self, object obj, [DefaultParameterValue(0)]int start) {
+ RequireNotFrozen(self);
+
// Note: Array#fill(obj, start) is not equivalent to Array#fill(obj, start, 0)
// (as per MRI behavior, the latter can expand the array if start > length, but the former doesn't)
start = Math.Max(0, NormalizeIndex(self, start));
@@ -976,6 +1046,10 @@ public static class IListOps {
[RubyMethod("fill")]
public static IList/*!*/ Fill(IList/*!*/ self, object obj, int start, int length) {
+ if (length > (int.MaxValue / 20)) { // This is roughly what MRI array max size is
+ throw RubyExceptions.CreateArgumentError("argument too big");
+ }
+
// Note: Array#fill(obj, start) is not equivalent to Array#fill(obj, start, 0)
// (as per MRI behavior, the latter can expand the array if start > length, but the former doesn't)
start = Math.Max(0, NormalizeIndex(self, start));
@@ -990,7 +1064,11 @@ public static class IListOps {
}
[RubyMethod("fill")]
- public static IList/*!*/ Fill(ConversionStorage<int>/*!*/ fixnumCast, IList/*!*/ self, object obj, object start, [DefaultParameterValue(null)]object length) {
+ public static IList/*!*/ Fill(ConversionStorage<int>/*!*/ fixnumCast, BlockParam block, IList/*!*/ self, object obj, object start, [DefaultParameterValue(null)]object length) {
+ if (block != null) { // 3 arguments requires no block be passed, but because of the way IronRuby selects methods, we must explicitly check for the block
+ throw RubyExceptions.CreateArgumentError("wrong number of arguments (3 for 0..2)");
+ }
+
int startFixnum = (start == null) ? 0 : Protocols.CastToFixnum(fixnumCast, start);
if (length == null) {
return Fill(self, obj, startFixnum);
@@ -1003,6 +1081,9 @@ public static class IListOps {
public static IList/*!*/ Fill(ConversionStorage<int>/*!*/ fixnumCast, IList/*!*/ self, object obj, [NotNull]Range/*!*/ range) {
int begin = NormalizeIndex(self, Protocols.CastToFixnum(fixnumCast, range.Begin));
int end = NormalizeIndex(self, Protocols.CastToFixnum(fixnumCast, range.End));
+ if (begin < 0 || end < 0) {
+ throw RubyExceptions.CreateRangeError("{0} out of range", range);
+ }
int length = Math.Max(0, end - begin + (range.ExcludeEnd ? 0 : 1));
return Fill(self, obj, begin, length);
@@ -1053,6 +1134,9 @@ public static class IListOps {
public static object Fill(ConversionStorage<int>/*!*/ fixnumCast, [NotNull]BlockParam/*!*/ block, IList/*!*/ self, [NotNull]Range/*!*/ range) {
int begin = NormalizeIndex(self, Protocols.CastToFixnum(fixnumCast, range.Begin));
int end = NormalizeIndex(self, Protocols.CastToFixnum(fixnumCast, range.End));
+ if (begin < 0 || end < 0) {
+ throw RubyExceptions.CreateRangeError("{0} out of range", range);
+ }
int length = Math.Max(0, end - begin + (range.ExcludeEnd ? 0 : 1));
return Fill(block, self, begin, length);
@@ -1322,6 +1406,23 @@ public static class IListOps {
}
[RubyMethod("rindex")]
+ public static Enumerator/*!*/ GetReverseIndexEnumerator(IList/*!*/ self) { // when rindex is called with no args and no block, we produce a reverse value enumerator. When the enumerator is each'ed over, if the block returns true, we return the index at which that happened
+ return new Enumerator((_, innerBlock) => {
+ object result;
+ for(int i=self.Count - 1; i >= 0; i--) {
+ if(innerBlock.Yield(self[i], out result)) {
+ return null; // block exited with break or similar
+ }
+ if(RubyOps.IsTrue(result)) {
+ return i;
+ }
+ }
+
+ return null;
+ });
+ }
+
+ [RubyMethod("rindex")]
public static object ReverseIndex([NotNull]BlockParam/*!*/ predicate, IList/*!*/ self) {
foreach (int i in IListOps.ReverseEnumerateIndexes(self)) {
object blockResult;
@@ -1529,6 +1630,10 @@ public static class IListOps {
return MutableString.CreateAscii("[...]");
}
MutableString str = MutableString.CreateMutable(RubyEncoding.Binary);
+ if (self.Count > 0) { // tainted empty arrays don't taint the inspect string if the array is empty
+ str.TaintBy(self, context);
+ }
+
str.Append('[');
bool first = true;
foreach (object obj in self) {
@@ -1537,7 +1642,10 @@ public static class IListOps {
} else {
str.Append(", ");
}
- str.Append(context.Inspect(obj));
+
+ var objInspected = context.Inspect(obj);
+ str.Append(objInspected);
+ str.TaintBy(objInspected);
}
str.Append(']');
return str;
@@ -1645,6 +1753,7 @@ public static class IListOps {
[RubyMethod("pop")]
public static object Pop(IList/*!*/ self) {
+ RequireNotFrozen(self);
if (self.Count == 0) {
return null;
}
@@ -1676,6 +1785,7 @@ public static class IListOps {
[RubyMethod("shift")]
public static object Shift(IList/*!*/ self) {
+ RequireNotFrozen(self);
if (self.Count == 0) {
return null;
}
@@ -1685,6 +1795,32 @@ public static class IListOps {
return result;
}
+ [RubyMethod("shift")]
+ public static object Shift(UnaryOpStorage/*!*/ allocateStorage, IList/*!*/ self, [DefaultProtocol]int elementCount) {
+ if (elementCount < 0) {
+ throw RubyExceptions.CreateArgumentError("negative array size");
+ }
+
+ RequireNotFrozen(self);
+
+ IList resultList = CreateResultArray(allocateStorage, self);
+
+ if (self.Count == 0) {
+ return resultList;
+ }
+
+ while (elementCount-- > 0) {
+ if (self.Count == 0) {
+ break;
+ }
+
+ object result = self[0];
+ self.RemoveAt(0);
+ resultList.Add(result);
+ }
+ return resultList;
+ }
+
[RubyMethod("unshift")]
public static IList/*!*/ Unshift(IList/*!*/ self, object/*!*/ arg) {
self.Insert(0, arg);
@@ -1725,15 +1861,25 @@ public static class IListOps {
IList result = GetElements(fixnumCast, allocateStorage, self, range);
int start, count;
- RangeToStartAndCount(fixnumCast, range, self.Count, out start, out count);
- DeleteElements(self, start, count);
- return result;
+ if (TryRangeToStartAndCount(fixnumCast, range, self.Count, out start, out count)) {
+ return SliceInPlace(allocateStorage, self, start, count);
+ } else { // out of range
+ return null;
+ }
}
[RubyMethod("slice!")]
public static IList SliceInPlace(UnaryOpStorage/*!*/ allocateStorage,
IList/*!*/ self, [DefaultProtocol]int start, [DefaultProtocol]int length) {
+ start = NormalizeIndex(self, start);
+
+ if (start > self.Count || start < 0) {
+ return null;
+ } else if (start == self.Count) {
+ return CreateResultArray(allocateStorage, self);
+ }
+
IList result = GetElements(allocateStorage, self, start, length);
DeleteElements(self, start, length);
return result;
@@ -1785,7 +1931,7 @@ public static class IListOps {
#endregion
- #region shuffle, shuffle!
+ #region shuffle, shuffle!, sample
[RubyMethod("shuffle")]
public static IList/*!*/ Shuffle(UnaryOpStorage/*!*/ allocateStorage, RubyArray/*!*/ self) {
@@ -1813,6 +1959,7 @@ public static class IListOps {
[RubyMethod("shuffle!")]
public static RubyArray/*!*/ ShuffleInPlace(RubyContext/*!*/ context, RubyArray/*!*/ self) {
+ self.RequireNotFrozen();
var generator = context.RandomNumberGenerator;
for (int i = self.Count - 1; i >= 0; i--) {
int j = generator.Next(i + 1);
@@ -1823,6 +1970,113 @@ public static class IListOps {
return self;
}
+ [RubyMethod("sample")]
+ public static object Sample(RubyContext/*!*/ context, IList/*!*/ self) {
+ var generator = context.RandomNumberGenerator;
+ if (self.Count == 0) {
+ return null;
+ }
+ return self[generator.Next(self.Count)];
+ }
+
+ [RubyMethod("sample")]
+ public static IList/*!*/ Sample(UnaryOpStorage/*!*/ allocateStorage, ConversionStorage<int>/*!*/ fixnumCast, IList/*!*/ self, object elementCount) {
+ return Sample(allocateStorage, self, Protocols.CastToFixnum(fixnumCast, elementCount));
+ }
+
+ [RubyMethod("sample")]
+ public static IList/*!*/ Sample(UnaryOpStorage/*!*/ allocateStorage, IList/*!*/ self, [DefaultProtocol]int elementCount) {
+ if (elementCount < 0) {
+ throw RubyExceptions.CreateArgumentError("negative sample number");
+ }
+
+ IList result = CreateResultArray(allocateStorage, self);
+ if (self.Count == 0) {
+ return result;
+ }
+
+ var generator = allocateStorage.Context.RandomNumberGenerator;
+
+ // we can't pick the same element twice, so remove items from a copy of the list as we pick them
+ var remaining = new List<object>(self.Count); // can't use ArrayList here as silverlight doesn't have it
+ foreach (var x in self)
+ remaining.Add(x);
+
+ while (remaining.Count > 0 && elementCount-- > 0) {
+ var idx = generator.Next(remaining.Count);
+ result.Add(remaining[idx]);
+ remaining.RemoveAt(idx);
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region rotate, rotate!
+
+ [RubyMethod("rotate")]
+ public static IList/*!*/ Rotate(UnaryOpStorage/*!*/ allocateStorage, IList/*!*/ self) {
+ return Rotate(allocateStorage, self, 1);
+ }
+
+ [RubyMethod("rotate")]
+ public static IList/*!*/ Rotate(UnaryOpStorage/*!*/ allocateStorage, IList/*!*/ self, [DefaultProtocol]int n) {
+ IList result = CreateResultArray(allocateStorage, self);
+ if (result is RubyArray) {
+ (result as RubyArray).AddCapacity(self.Count);
+ }
+ for (int i = 0; i< self.Count; i++ ) {
+ var idx = NormalizeIndex(self, (i + n) % self.Count ); // we can have negative n which rotates backwards
+ result.Add(self[idx]);
+ }
+ return result;
+ }
+
+ [RubyMethod("rotate!")]
+ public static IList/*!*/ InPlaceRotate(IList/*!*/ self) {
+ return InPlaceRotate(self, 1);
+ }
+
+ [RubyMethod("rotate!")]
+ public static IList/*!*/ InPlaceRotate(IList/*!*/ self, [DefaultProtocol]int n) {
+ RequireNotFrozen(self);
+
+ var count = self.Count;
+ if (count == 0 || count == 1)
+ return self;
+
+ n = n % count;
+ if (n == 0)
+ return self;
+
+ var tmp = new object[Math.Abs(n)];
+ if (n > 0) {
+ for (int i = 0; i < n; i++) { // copy parts that will get overwritten
+ tmp[i] = self[i];
+ }
+ for (int i = n; i < count; i++) { // shift down
+ self[i - n] = self[i];
+ }
+ for (int i = 0; i < n; i++) { // restore overwritten
+ self[count - n + i] = tmp[i];
+ }
+ } else { // negative n
+ n = -n;
+ for (int i = n; i > 0; i--) { // copy parts that will get overwritten
+ tmp[n - i] = self[count - i];
+ }
+ for (int i = count - n - 1; i >= 0; i--) { // shift up
+ self[i + n] = self[i];
+ }
+ for (int i = 0; i < n; i++) { // restore overwritten
+ self[i] = tmp[i];
+ }
+ }
+
+ return self;
+ }
+
#endregion
#region reverse, reverse!, transpose, uniq, uniq!
@@ -1881,30 +2135,36 @@ public static class IListOps {
}
[RubyMethod("uniq")]
- public static IList/*!*/ Unique(UnaryOpStorage/*!*/ allocateStorage, IList/*!*/ self) {
+ public static IList/*!*/ Unique(UnaryOpStorage/*!*/ allocateStorage, BlockParam block, IList/*!*/ self) {
IList result = CreateResultArray(allocateStorage, self);
var seen = new Dictionary<object, bool>(allocateStorage.Context.EqualityComparer);
bool nilSeen = false;
- AddUniqueItems(self, result, seen, ref nilSeen);
+ AddUniqueItems(block, self, result, seen, ref nilSeen);
return result;
}
[RubyMethod("uniq!")]
- public static IList UniqueSelf(UnaryOpStorage/*!*/ hashStorage, BinaryOpStorage/*!*/ eqlStorage, RubyArray/*!*/ self) {
+ public static IList UniqueSelf(UnaryOpStorage/*!*/ hashStorage, BinaryOpStorage/*!*/ eqlStorage, BlockParam block, RubyArray/*!*/ self) {
self.RequireNotFrozen();
- return UniqueSelf(hashStorage, eqlStorage, (IList)self);
+ return UniqueSelf(hashStorage, eqlStorage, block, (IList)self);
}
[RubyMethod("uniq!")]
- public static IList UniqueSelf(UnaryOpStorage/*!*/ hashStorage, BinaryOpStorage/*!*/ eqlStorage, IList/*!*/ self) {
- var seen = new Dictionary<object, bool>(new EqualityComparer(hashStorage, eqlStorage));
+ public static IList UniqueSelf(UnaryOpStorage/*!*/ hashStorage, BinaryOpStorage/*!*/ eqlStorage, BlockParam block, IList/*!*/ self) {
+ IEqualityComparer<object> comparer = new EqualityComparer(hashStorage, eqlStorage);
+ var seen = new Dictionary<object, bool>(comparer);
bool nilSeen = false;
bool modified = false;
int i = 0;
while (i < self.Count) {
- object key = self[i];
+ object item = self[i];
+ object key;
+ if (block == null || block.Yield(item, out key)) {
+ key = item;
+ }
+
if (key != null && !seen.ContainsKey(key)) {
seen.Add(key, true);
i++;
@@ -1912,8 +2172,15 @@ public static class IListOps {
nilSeen = true;
i++;
} else {
- self.RemoveAt(i);
+ // removing objects modifies the array... which breaks the dictionary if "seen" is a self-referential array
+ bool isRecursiveArray = seen.Remove(self);
+
+ self.RemoveAt(i);
modified = true;
+
+ if (isRecursiveArray) {
+ seen.Add(self, true); // self.hash will change
+ }
}
}
View
94 Languages/Ruby/Libraries/Initializers.Generated.cs
@@ -1347,8 +1347,8 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "zip", 0x51,
- 0x80040008U,
- new Func<IronRuby.Runtime.CallSiteStorage<Func<System.Runtime.CompilerServices.CallSite, System.Object, IronRuby.Builtins.Proc, System.Object>>, IronRuby.Runtime.BlockParam, System.Object, System.Collections.IList[], System.Object>(IronRuby.Builtins.Enumerable.Zip)
+ 0x80100020U,
+ new Func<IronRuby.Runtime.CallSiteStorage<Func<System.Runtime.CompilerServices.CallSite, System.Object, IronRuby.Builtins.Proc, System.Object>>, IronRuby.Runtime.ConversionStorage<System.Collections.IList>, IronRuby.Runtime.CallSiteStorage<Func<System.Runtime.CompilerServices.CallSite, System.Object, IronRuby.Builtins.Proc, System.Object>>, IronRuby.Runtime.BlockParam, System.Object, System.Object[], System.Object>(IronRuby.Builtins.Enumerable.Zip)
);
}
@@ -3024,11 +3024,11 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "readlines", 0x51,
- 0x00000000U, 0x00020004U, 0x00060000U, 0x00000000U,
+ 0x00000000U, 0x00000000U, 0x00020004U, 0x00060000U,
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines),
new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, Microsoft.Scripting.Runtime.DynamicNull, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines),
new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Runtime.Union<IronRuby.Builtins.MutableString, System.Int32>, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Builtins.MutableString, System.Int32, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines)
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.RubyIO, IronRuby.Builtins.MutableString, System.Int32, IronRuby.Builtins.RubyArray>(IronRuby.Builtins.RubyIOOps.ReadLines)
);
DefineLibraryMethod(module, "readpartial", 0x51,
@@ -4250,15 +4250,15 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "define_singleton_method", 0x51,
- new[] { 0x0000000cU, 0x0002000cU, 0x0000000cU, 0x0002000cU, 0x0000000cU, 0x0004000aU, 0x0000000aU, 0x0002000cU},
- new Func<IronRuby.Runtime.RubyScope, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.Proc, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
+ new[] { 0x0002000cU, 0x0000000cU, 0x0002000cU, 0x0000000cU, 0x0004000aU, 0x0000000aU, 0x0002000cU, 0x0000000cU},
new Func<IronRuby.Runtime.RubyScope, System.Object, System.String, IronRuby.Builtins.RubyMethod, IronRuby.Builtins.RubyMethod>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.RubyMethod, IronRuby.Builtins.RubyMethod>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, System.Object, System.String, IronRuby.Builtins.UnboundMethod, IronRuby.Builtins.UnboundMethod>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.UnboundMethod, IronRuby.Builtins.UnboundMethod>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, IronRuby.Runtime.BlockParam, System.Object, System.String, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
new Func<IronRuby.Runtime.RubyScope, IronRuby.Runtime.BlockParam, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
- new Func<IronRuby.Runtime.RubyScope, System.Object, System.String, IronRuby.Builtins.Proc, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod)
+ new Func<IronRuby.Runtime.RubyScope, System.Object, System.String, IronRuby.Builtins.Proc, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod),
+ new Func<IronRuby.Runtime.RubyScope, System.Object, IronRuby.Runtime.ClrName, IronRuby.Builtins.Proc, IronRuby.Builtins.Proc>(IronRuby.Builtins.KernelOps.DefineSingletonMethod)
);
DefineLibraryMethod(module, "display", 0x51,
@@ -6850,11 +6850,11 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "each_line", 0x51,
- 0x00000002U, 0x00010000U, 0x00020001U, 0x00000000U,
+ 0x00000000U, 0x00000002U, 0x00010000U, 0x00020001U,
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine),
new Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine),
new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine),
- new Func<IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine)
+ new Func<IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine)
);
DefineLibraryMethod(module, "empty?", 0x51,
@@ -6965,11 +6965,11 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "lines", 0x51,
- 0x00000002U, 0x00010000U, 0x00020001U, 0x00000000U,
+ 0x00000000U, 0x00000002U, 0x00010000U, 0x00020001U,
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine),
new Func<IronRuby.Runtime.RubyContext, IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine),
new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine),
- new Func<IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.Builtins.MutableString, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.MutableStringOps.EachLine)
+ new Func<IronRuby.Runtime.BlockParam, IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.EachLine)
);
DefineLibraryMethod(module, "ljust", 0x51,
@@ -7030,10 +7030,10 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "rindex", 0x51,
- 0x00010002U, 0x00030002U, 0x00040004U,
+ 0x00040004U, 0x00010002U, 0x00030002U,
+ new Func<IronRuby.Runtime.RubyScope, IronRuby.Builtins.MutableString, IronRuby.Builtins.RubyRegex, System.Int32, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf),
new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf),
- new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Int32, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf),
- new Func<IronRuby.Runtime.RubyScope, IronRuby.Builtins.MutableString, IronRuby.Builtins.RubyRegex, System.Int32, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf)
+ new Func<IronRuby.Builtins.MutableString, IronRuby.Builtins.MutableString, System.Int32, System.Object>(IronRuby.Builtins.MutableStringOps.LastIndexOf)
);
DefineLibraryMethod(module, "rjust", 0x51,
@@ -7840,11 +7840,12 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "[]=", 0x51,
- 0x00010000U, 0x00010000U, 0x00060000U, 0x00000008U,
+ new[] { 0x00010000U, 0x00010000U, 0x00000000U, 0x00060000U, 0x00000000U},
new Func<IronRuby.Builtins.RubyArray, System.Int32, System.Object, System.Object>(IronRuby.Builtins.IListOps.SetElement),
new Func<System.Collections.IList, System.Int32, System.Object, System.Object>(IronRuby.Builtins.IListOps.SetElement),
+ new Func<IronRuby.Runtime.ConversionStorage<System.Collections.IList>, IronRuby.Runtime.ConversionStorage<System.Int32>, System.Collections.IList, System.Object, System.Object, System.Object, System.Object>(IronRuby.Builtins.IListOps.SetElement),
new Func<IronRuby.Runtime.ConversionStorage<System.Collections.IList>, System.Collections.IList, System.Int32, System.Int32, System.Object, System.Object>(IronRuby.Builtins.IListOps.SetElement),
- new Func<IronRuby.Runtime.ConversionStorage<System.Collections.IList>, IronRuby.Runtime.ConversionStorage<System.Int32>, System.Collections.IList, IronRuby.Builtins.Range, System.Object, System.Object>(IronRuby.Builtins.IListOps.SetElement)
+ new Func<IronRuby.Runtime.ConversionStorage<System.Collections.IList>, IronRuby.Runtime.ConversionStorage<System.Int32>, System.Collections.IList, System.Object, System.Object, System.Object>(IronRuby.Builtins.IListOps.SetElement)
);
DefineLibraryMethod(module, "|", 0x51,
@@ -7968,7 +7969,7 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
new[] { 0x00000000U, 0x00000000U, 0x00000000U, 0x00000008U, 0x00000001U, 0x00000001U, 0x00000002U, 0x0000000aU},
new Func<System.Collections.IList, System.Object, System.Int32, System.Collections.IList>(IronRuby.Builtins.IListOps.Fill),
new Func<System.Collections.IList, System.Object, System.Int32, System.Int32, System.Collections.IList>(IronRuby.Builtins.IListOps.Fill),
- new Func<IronRuby.Runtime.ConversionStorage<System.Int32>, System.Collections.IList, System.Object, System.Object, System.Object, System.Collections.IList>(IronRuby.Builtins.IListOps.Fill),
+ new Func<IronRuby.Runtime.ConversionStorage<System.Int32>, IronRuby.Runtime.BlockParam, System.Collections.IList, System.Object, System.Object, System.Object, System.Collections.IList>(IronRuby.Builtins.IListOps.Fill),
new Func<IronRuby.Runtime.ConversionStorage<System.Int32>, System.Collections.IList, System.Object, IronRuby.Builtins.Range, System.Collections.IList>(IronRuby.Builtins.IListOps.Fill),
new Func<IronRuby.Runtime.BlockParam, System.Collections.IList, System.Int32, System.Object>(IronRuby.Builtins.IListOps.Fill),
new Func<IronRuby.Runtime.BlockParam, System.Collections.IList, System.Int32, System.Int32, System.Object>(IronRuby.Builtins.IListOps.Fill),
@@ -8048,6 +8049,11 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
new Func<IronRuby.Runtime.JoinConversionStorage, IronRuby.Runtime.ConversionStorage<IronRuby.Builtins.MutableString>, System.Collections.IList, System.Object, IronRuby.Builtins.MutableString>(IronRuby.Builtins.IListOps.JoinWithLazySeparatorConversion)
);
+ DefineLibraryMethod(module, "keep_if", 0x51,
+ 0x00000000U,
+ new Func<IronRuby.Runtime.BlockParam, System.Collections.IList, System.Object>(IronRuby.Builtins.IListOps.KeepIf)
+ );
+
DefineLibraryMethod(module, "last", 0x51,
0x00000000U, 0x00010000U,
new Func<System.Collections.IList, System.Object>(IronRuby.Builtins.IListOps.Last),
@@ -8086,8 +8092,8 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "product", 0x51,
- 0x80010002U,
- new Func<System.Collections.IList, System.Collections.IList[], IronRuby.Builtins.RubyArray>(IronRuby.Builtins.IListOps.Product)
+ 0x80020004U,
+ new Func<IronRuby.Runtime.BlockParam, System.Collections.IList, System.Collections.IList[], System.Collections.IList>(IronRuby.Builtins.IListOps.Product)
);
DefineLibraryMethod(module, "push", 0x51,
@@ -8132,14 +8138,40 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
);
DefineLibraryMethod(module, "rindex", 0x51,
- 0x00000001U, 0x00000000U,
+ 0x00000000U, 0x00000001U, 0x00000000U,
+ new Func<System.Collections.IList, IronRuby.Builtins.Enumerator>(IronRuby.Builtins.IListOps.GetReverseIndexEnumerator),
new Func<IronRuby.Runtime.BlockParam, System.Collections.IList, System.Object>(IronRuby.Builtins.IListOps.ReverseIndex),
new Func<IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BlockParam, System.Collections.IList, System.Object, System.Object>(IronRuby.Builtins.IListOps.ReverseIndex)
);
- DefineLibraryMethod(module, "shift", 0x51,
+ DefineLibraryMethod(module, "rotate", 0x51,
+ 0x00000000U, 0x00020000U,
+ new Func<IronRuby.Runtime.UnaryOpStorage, System.Collections.IList, System.Collections.IList>(IronRuby.Builtins.IListOps.Rotate),
+ new Func<IronRuby.Runtime.UnaryOpStorage, System.Collections.IList, System.Int32, System.Collections.IList>(IronRuby.Builtins.IListOps.Rotate)
+ );
+
+ DefineLibraryMethod(module, "rotate!", 0x51,
+ 0x00000000U, 0x00010000U,
+ new Func<System.Collections.IList, System.Collections.IList>(IronRuby.Builtins.IListOps.InPlaceRotate),
+ new Func<System.Collections.IList, System.Int32, System.Collections.IList>(IronRuby.Builtins.IListOps.InPlaceRotate)
+ );
+
+ DefineLibraryMethod(module, "sample", 0x51,
+ 0x00000000U, 0x00000000U, 0x00020000U,
+ new Func<IronRuby.Runtime.RubyContext, System.Collections.IList, System.Object>(IronRuby.Builtins.IListOps.Sample),
+ new Func<IronRuby.Runtime.UnaryOpStorage, IronRuby.Runtime.ConversionStorage<System.Int32>, System.Collections.IList, System.Object, System.Collections.IList>(IronRuby.Builtins.IListOps.Sample),
+ new Func<IronRuby.Runtime.UnaryOpStorage, System.Collections.IList, System.Int32, System.Collections.IList>(IronRuby.Builtins.IListOps.Sample)
+ );
+
+ DefineLibraryMethod(module, "select!", 0x51,
0x00000000U,
- new Func<System.Collections.IList, System.Object>(IronRuby.Builtins.IListOps.Shift)
+ new Func<IronRuby.Runtime.BlockParam, System.Collections.IList, System.Object>(IronRuby.Builtins.IListOps.SelectInPlace)
+ );
+
+ DefineLibraryMethod(module, "shift", 0x51,
+ 0x00000000U, 0x00020000U,
+ new Func<System.Collections.IList, System.Object>(IronRuby.Builtins.IListOps.Shift),
+ new Func<IronRuby.Runtime.UnaryOpStorage, System.Collections.IList, System.Int32, System.Object>(IronRuby.Builtins.IListOps.Shift)
);
DefineLibraryMethod(module, "shuffle", 0x51,
@@ -8203,13 +8235,13 @@ public sealed class BuiltinsLibraryInitializer : IronRuby.Builtins.LibraryInitia
DefineLibraryMethod(module, "uniq", 0x51,
0x00000000U,
- new Func<IronRuby.Runtime.UnaryOpStorage, System.Collections.IList, System.Collections.IList>(IronRuby.Builtins.IListOps.Unique)
+ new Func<IronRuby.Runtime.UnaryOpStorage, IronRuby.Runtime.BlockParam, System.Collections.IList, System.Collections.IList>(IronRuby.Builtins.IListOps.Unique)
);
DefineLibraryMethod(module, "uniq!", 0x51,
0x00000000U, 0x00000000U,
- new Func<IronRuby.Runtime.UnaryOpStorage, IronRuby.Runtime.BinaryOpStorage, IronRuby.Builtins.RubyArray, System.Collections.IList>(IronRuby.Builtins.IListOps.UniqueSelf),
- new Func<IronRuby.Runtime.UnaryOpStorage, IronRuby.Runtime.BinaryOpStorage, System.Collections.IList, System.Collections.IList>(IronRuby.Builtins.IListOps.UniqueSelf)
+ new Func<IronRuby.Runtime.UnaryOpStorage, IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BlockParam, IronRuby.Builtins.RubyArray, System.Collections.IList>(IronRuby.Builtins.IListOps.UniqueSelf),
+ new Func<IronRuby.Runtime.UnaryOpStorage, IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BlockParam, System.Collections.IList, System.Collections.IList>(IronRuby.Builtins.IListOps.UniqueSelf)
);
DefineLibraryMethod(module, "unshift", 0x51,
@@ -11520,12 +11552,12 @@ public sealed class BigDecimalLibraryInitializer : IronRuby.Builtins.LibraryInit
);
DefineLibraryMethod(module, "<=>", 0x11,
- new[] { 0x00000000U, 0x00000002U, 0x00000004U, 0x00000000U, 0x00000000U},
- new Func<IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BinaryOpStorage, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Object, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
+ new[] { 0x00000002U, 0x00000004U, 0x00000000U, 0x00000000U, 0x00000000U},
new Func<IronRuby.StandardLibrary.BigDecimal.BigDecimal, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
new Func<IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.BigDecimal.BigDecimal, Microsoft.Scripting.Math.BigInteger, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
new Func<IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Int32, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
- new Func<IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Double, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare)
+ new Func<IronRuby.Runtime.RubyContext, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Double, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare),
+ new Func<IronRuby.Runtime.BinaryOpStorage, IronRuby.Runtime.BinaryOpStorage, IronRuby.StandardLibrary.BigDecimal.BigDecimal, System.Object, System.Object>(IronRuby.StandardLibrary.BigDecimal.BigDecimalOps.Compare)
);
DefineLibraryMethod(module, "==", 0x11,
View
6 Languages/Ruby/Ruby/Builtins/RubyArray.cs
@@ -142,12 +142,12 @@ public RubyArray(IEnumerable/*!*/ items)
public void RequireNotFrozen() {
if ((_flags & IsFrozenFlag) != 0) {
// throw in a separate method to allow inlining of the current one
- ThrowObjectFrozenException();
+ ThrowArrayFrozenException();
}
}
- private static void ThrowObjectFrozenException() {
- throw RubyExceptions.CreateObjectFrozenError();
+ private static void ThrowArrayFrozenException() {
+ throw RubyExceptions.CreateArrayFrozenError();
}
private void Mutate() {
View
4 Languages/Ruby/Ruby/Runtime/RubyExceptions.cs
@@ -48,6 +48,10 @@ public static class RubyExceptions {
return CreateRuntimeError("can't modify frozen object");
}
+ public static Exception/*!*/ CreateArrayFrozenError() {
+ return CreateRuntimeError("can't modify frozen array");
+ }
+
public static Exception/*!*/ CreateTypeConversionError(string/*!*/ fromType, string/*!*/ toType) {
Assert.NotNull(fromType, toType);
return CreateTypeError("can't convert {0} into {1}", fromType, toType);
View
5 Languages/Ruby/Ruby/Runtime/RubyOps.cs
@@ -2139,8 +2139,11 @@ private sealed class _NeedsUpdate {
[Emitted] // ProtocolConversionAction
public static IList/*!*/ ToArrayValidator(string/*!*/ className, object obj) {
+ if (obj == null) // to_ary is allowed to return nil
+ return null;
+
var result = obj as IList;
- if (result == null) {
+ if (result == null) { // but it's not allowed to return other types
throw RubyExceptions.CreateReturnTypeError(className, "to_ary", "Array");
}
return result;
Something went wrong with that request. Please try again.