add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Experimental/Regex/Slice.rb File: Slice.rb =================================================================== --- [no source file] +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Experimental/Regex/Slice.rb;RangeFixes @@ -1,0 +1,15 @@ +class R < Range + def exclude_end? + p "foooo" + true + end +end + +/(a)(b)(c)(d)(e)?(f)?(g)?(h)?/ =~ "abcd" +p $1, $2, $3, $4, $5, $6, $7, $8, $9, $10 +p $+ +p $~[R.new(1,-1)] + + +x = [1,2,3,4,5,6] +p x[R.new(1,-1)] \ No newline at end of file =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MatchDataOps.cs;C443395 File: MatchDataOps.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MatchDataOps.cs;C443395 (server) 5/24/2008 6:23 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MatchDataOps.cs;RangeFixes @@ -17,6 +17,7 @@ using Microsoft.Scripting.Actions; using Microsoft.Scripting.Runtime; using Ruby.Runtime; +using System.Text.RegularExpressions; namespace Ruby.Builtins { [RubyClass("MatchData", Extends = typeof(MatchData), Inherits = typeof(Object))] @@ -47,14 +48,17 @@ [RubyMethod("[]")] public static RubyArray GetGroup(CodeContext/*!*/ context, MatchData/*!*/ self, int start, int length) { - start = IListOps.NormalizeIndex(self.Groups.Count, start); - if (length < 0 || start < 0 || start > self.Groups.Count) + if (!IListOps.NormalizeRange(self.Groups.Count, ref start, ref length)) { return null; + } - int end = start + length > self.Groups.Count ? self.Groups.Count : start + length; RubyArray result = new RubyArray(); - for (int i = start; i < end; ++i) - result.Add(Kernel.FlowTaint(context, self, MutableString.Create(self.Groups[i].Value))); + for (int i = 0; i < length; i++) { + Group group = self.Groups[start + i]; + MutableString value = group.Success ? MutableString.Create(group.Value) : null; + result.Add(Kernel.FlowTaint(context, self, value)); + } + return result; } @@ -65,10 +69,11 @@ [RubyMethod("[]")] public static RubyArray GetGroup(CodeContext/*!*/ context, MatchData/*!*/ self, Range range) { - int begin = Protocols.CastToFixnum(context, range.Begin); - int end = Protocols.CastToFixnum(context, range.End); - int length = range.ExcludeEnd ? end - begin : end - begin + 1; - return GetGroup(context, self, begin, length); + int begin, count; + if (!IListOps.NormalizeRange(context, self.Groups.Count, range, out begin, out count)) { + return null; + } + return GetGroup(context, self, begin, count); } private static void AssertValidGroup(MatchData/*!*/ self, int group) { =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MutableStringOps.cs;C448462 File: MutableStringOps.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MutableStringOps.cs;C448462 (server) 5/24/2008 2:28 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MutableStringOps.cs;RangeFixes @@ -2767,6 +2767,10 @@ // This method uses the tokenizer to auto-detect the base type -- happens when agument to to_i is 0 private static object ParseInteger(CodeContext/*!*/ context, string/*!*/ str) { bool isNegative = false; + if (str.Length == 0) { + return RuntimeHelpers.Int32ToObject(0); + } + str = ParseSign(str, ref isNegative); Tokenizer tokenizer = new Tokenizer(false, ErrorSink.Null); =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Extensions/IListOps.cs;C443395 File: IListOps.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Extensions/IListOps.cs;C443395 (server) 5/24/2008 6:19 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Extensions/IListOps.cs;RangeFixes @@ -47,6 +47,36 @@ return index < 0 ? index + count : index; } + internal static bool NormalizeRange(int listCount, ref int start, ref int count) { + start = NormalizeIndex(listCount, start); + if (start < 0 || start > listCount || count < 0) { + return false; + } + + if (count != 0) { + count = start + count > listCount ? listCount - start : count; + } + + return true; + } + + internal static bool NormalizeRange(CodeContext/*!*/ context, int listCount, Range/*!*/ range, out int begin, out int count) { + begin = Protocols.CastToFixnum(context, RubySites.RangeBegin(context, range)); + int end = Protocols.CastToFixnum(context, RubySites.RangeEnd(context, range)); + + begin = NormalizeIndex(listCount, begin); + + if (begin < 0 || begin > listCount) { + count = 0; + return false; + } + + end = NormalizeIndex(listCount, end); + + count = range.ExcludeEnd ? end - begin : end - begin + 1; + return true; + } + private static bool InRangeNormalized(IList/*!*/ list, ref int index) { if (index < 0) { index = index + list.Count; @@ -268,16 +298,10 @@ [RubyMethod("[]")] [RubyMethod("slice")] public static IList GetElements(CodeContext/*!*/ context, IList/*!*/ list, int index, int count) { - index = NormalizeIndex(list, index); - if (index < 0 || index > list.Count || count < 0) { + if (!NormalizeRange(list.Count, ref index, ref count)) { return null; } - if (count == 0) { - return CreateResultArray(context, list); - } - - count = index + count > list.Count ? list.Count - index : count; return GetResultRange(context, list, index, count); } @@ -302,18 +326,12 @@ [RubyMethod("[]")] [RubyMethod("slice")] public static IList GetElement(CodeContext/*!*/ context, IList array, Range range) { - int begin = Protocols.CastToFixnum(context, RubySites.RangeBegin(context, range)); - int end = Protocols.CastToFixnum(context, RubySites.RangeEnd(context, range)); - - begin = NormalizeIndex(array, begin); - - if (begin < 0 || begin > array.Count) + int start, count; + if (!NormalizeRange(context, array.Count, range, out start, out count)) { return null; - - end = NormalizeIndex(array, end); - - int count = RubySites.RangeExcludeEnd(context, range) ? end - begin : end - begin + 1; - return count < 0 ? CreateResultArray(context, array) : GetElements(context, array, begin, count); + } + + return count < 0 ? CreateResultArray(context, array) : GetElements(context, array, start, count); } #endregion ===================================================================