public static object EachObject(BlockParam block, RubyModule/*!*/ self, [NotNull]RubyClass/*!*/ theClass) { Type classType = theClass.GetType(); bool isClass = (classType == typeof(RubyClass)); if (!isClass && classType != typeof(RubyModule)) { throw new NotSupportedException("each_object only supported for objects of type Class or Module"); } if (block == null) { throw RubyExceptions.NoBlockGiven(); } Dictionary<RubyModule, object> visited = new Dictionary<RubyModule, object>(); Stack<RubyModule> modules = new Stack<RubyModule>(); modules.Push(theClass.Context.ObjectClass); while (modules.Count > 0) { RubyModule next = modules.Pop(); RubyClass asClass = next as RubyClass; if (!isClass || asClass != null) { object result; if (block.Yield(next, out result)) { return result; } } next.EnumerateConstants(delegate(RubyModule module, string name, object value) { RubyModule constAsModule = (value as RubyModule); if (constAsModule != null && !visited.ContainsKey(constAsModule)) { modules.Push(constAsModule); visited[module] = null; } return false; }); } return visited.Count; }
public static object Synchronize(BlockParam criticalSection, RubyMutex/*!*/ self) { lock (self._mutex) { self._isLocked = true; try { object result; criticalSection.Yield(out result); return result; } finally { self._isLocked = false; } } }
public static RubyArray Map(RubyContext/*!*/ context, BlockParam collector, object self) { RubyArray result = new RubyArray(); Each(context, self, Proc.Create(context, delegate(BlockParam/*!*/ selfBlock, object item) { if (collector != null) { if (collector.Yield(item, out item)) { return item; } } result.Add(item); return null; })); return result; }
public static object Each(BlockParam block, IEnumerable/*!*/ self) { foreach (object obj in self) { object result; if (block == null) { throw RubyExceptions.NoBlockGiven(); } if (block.Yield(obj, out result)) { return result; } } return self; }
public static RubyArray Map(CallSiteStorage<EachSite>/*!*/ each, BlockParam collector, object self) { RubyArray result = new RubyArray(); Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (collector != null) { if (collector.Yield(item, out item)) { return item; } } result.Add(item); return null; })); return result; }
public static object EachType(RubyContext/*!*/ context, BlockParam/*!*/ block, TypeGroup/*!*/ self) { if (block == null) { throw RubyExceptions.NoBlockGiven(); } foreach (Type type in self.Types) { RubyModule module = context.GetModule(type); object result; if (block.Yield(module, out result)) { return result; } } return self; }
public static object Each(BlockParam block, RubyStruct/*!*/ self) { if (block == null && self.ItemCount > 0) { throw RubyExceptions.NoBlockGiven(); } foreach (var value in self.Values) { object result; if (block.Yield(value, out result)) { return result; } } return self; }
public static object EachPair(BlockParam block, RubyStruct/*!*/ self) { if (block == null && self.ItemCount > 0) { throw RubyExceptions.NoBlockGiven(); } var context = self.ImmediateClass.Context; foreach (KeyValuePair<string, object> entry in self.GetItems()) { object result; if (block.Yield(context.EncodeIdentifier(entry.Key), entry.Value, out result)) { return result; } } return self; }
public static object Trap( RubyContext/*!*/ context, BlockParam block, object self, object signalId) { if ((signalId is MutableString) && ((MutableString)signalId).ConvertToString() == "INT") { context.InterruptSignalHandler = delegate() { object result; block.Yield(out result); }; } else { // TODO: For now, just ignore unknown signals. This should be changed to throw an // exception. We are not doing it yet as it is close to the V1 RTM, and throwing // an exception might cause some app to misbehave whereas it might have happenned // to work if no exception is thrown } return null; }
public static object ChangeDirectory(BlockParam block, object/*!*/ self, MutableString dir) { string strDir = dir.ConvertToString(); if (block == null) { SetCurrentDirectory(strDir); return 0; } else { string current = Directory.GetCurrentDirectory(); try { SetCurrentDirectory(strDir); object result; block.Yield(dir, out result); return result; } finally { SetCurrentDirectory(current); } } }
private static object TrueForItems(CallSiteStorage<EachSite>/*!*/ each, BlockParam predicate, object self, bool expected) { bool result = expected; Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (predicate != null) { if (predicate.Yield(item, out item)) { return item; } } bool isTrue = Protocols.IsTrue(item); if (isTrue != result) { result = isTrue; return selfBlock.Break(ScriptingRuntimeHelpers.BooleanToObject(isTrue)); } return null; })); return ScriptingRuntimeHelpers.BooleanToObject(result); }
public static object DeleteIf(RubyContext/*!*/ context, BlockParam block, object/*!*/ self) { PlatformAdaptationLayer pal = context.DomainManager.Platform; IDictionary variables = pal.GetEnvironmentVariables(); if (variables.Count > 0 && block == null) { throw RubyExceptions.NoBlockGiven(); } foreach (DictionaryEntry entry in variables) { MutableString key = MutableString.Create(entry.Key.ToString()).Freeze(); MutableString value = MutableString.Create(entry.Value.ToString()).Freeze(); object result; if (block.Yield(key, value, out result)) { return result; } if (RubyOps.IsTrue(result)) { SetVariable(context, self, key, null); } } return self; }
public static object EachObject(BlockParam block, RubyModule/*!*/ self, [NotNull]RubyClass/*!*/ theClass) { if (!theClass.HasAncestor(self.Context.ModuleClass)) { throw RubyExceptions.CreateRuntimeError("each_object only supported for objects of type Class or Module"); } if (block == null) { throw RubyExceptions.NoBlockGiven(); } int matches = 0; List<RubyModule> visitedModules = new List<RubyModule>(); Stack<RubyModule> pendingModules = new Stack<RubyModule>(); pendingModules.Push(theClass.Context.ObjectClass); while (pendingModules.Count > 0) { RubyModule next = pendingModules.Pop(); visitedModules.Add(next); if (theClass.Context.IsKindOf(next, theClass)) { matches++; object result; if (block.Yield(next, out result)) { return result; } } using (theClass.Context.ClassHierarchyLocker()) { next.EnumerateConstants(delegate(RubyModule module, string name, object value) { RubyModule constAsModule = value as RubyModule; if (constAsModule != null && !visitedModules.Contains(constAsModule)) { pendingModules.Push(constAsModule); } return false; }); } } return matches; }
private static object TrueForItems(CallSiteStorage<EachSite>/*!*/ each, BlockParam predicate, object self, bool stop, bool positiveResult) { object result = ScriptingRuntimeHelpers.BooleanToObject(!positiveResult); Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (predicate != null) { object blockResult; if (predicate.Yield(item, out blockResult)) { result = blockResult; return selfBlock.PropagateFlow(predicate, blockResult); } item = blockResult; } bool isTrue = Protocols.IsTrue(item); if (isTrue == stop) { result = ScriptingRuntimeHelpers.BooleanToObject(positiveResult); return selfBlock.Break(result); } return null; })); return result; }
public static object GetProfile(RubyContext/*!*/ context, BlockParam/*!*/ block, object self) { if (!((RubyOptions)context.Options).Profile) { throw RubyExceptions.CreateSystemCallError("You must enable profiling to use Clr.profile"); } var start = Profiler.Instance.GetProfile(); object blockResult; if (block.Yield(out blockResult)) { return blockResult; } Hash result = new Hash(context); foreach (var entry in Profiler.Instance.GetProfile()) { long startTime; if (!start.TryGetValue(entry.Key, out startTime)) { startTime = 0; } long elapsed = entry.Value - startTime; if (elapsed > 0) { result[entry.Key] = Protocols.Normalize(Utils.DateTimeTicksFromStopwatch(elapsed)); } } return result; }
public static RubyArray/*!*/ SortBy( CallSiteStorage<EachSite>/*!*/ each, BinaryOpStorage/*!*/ comparisonStorage, BinaryOpStorage/*!*/ lessThanStorage, BinaryOpStorage/*!*/ greaterThanStorage, BlockParam keySelector, object self) { // collect key, value pairs List<KeyValuePair<object, object>> keyValuePairs = new List<KeyValuePair<object, object>>(); // Collect the key, value pairs Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (keySelector == null) { throw RubyExceptions.NoBlockGiven(); } object key; if (keySelector.Yield(item, out key)) { return key; } keyValuePairs.Add(new KeyValuePair<object, object>(key, item)); return null; })); // sort by keys keyValuePairs.Sort(delegate(KeyValuePair<object, object> x, KeyValuePair<object, object> y) { return Protocols.Compare(comparisonStorage, lessThanStorage, greaterThanStorage, x.Key, y.Key); }); // return values RubyArray result = new RubyArray(keyValuePairs.Count); foreach (KeyValuePair<object, object> pair in keyValuePairs) { result.Add(pair.Value); } return result; }
public static RubyArray/*!*/ Partition(CallSiteStorage<EachSite>/*!*/ each, BlockParam predicate, object self) { RubyArray trueSet = new RubyArray(); RubyArray falseSet = new RubyArray(); Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (predicate == null) { throw RubyExceptions.NoBlockGiven(); } object blockResult; if (predicate.Yield(item, out blockResult)) { return blockResult; } if (Protocols.IsTrue(blockResult)) { trueSet.Add(item); } else { falseSet.Add(item); } return null; })); RubyArray pair = new RubyArray(2); pair.Add(trueSet); pair.Add(falseSet); return pair; }
private static object GetExtreme( CallSiteStorage<EachSite>/*!*/ each, BinaryOpStorage/*!*/ compareStorage, BinaryOpStorage/*!*/ lessThanStorage, BinaryOpStorage/*!*/ greaterThanStorage, BlockParam comparer, object self, int comparisonValue) { bool firstItem = true; object result = null; Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { // Check for first element if (firstItem) { result = item; firstItem = false; return null; } int compareResult; if (comparer != null) { object blockResult; if (comparer.Yield(result, item, out blockResult)) { return blockResult; } if (blockResult == null) { throw RubyExceptions.MakeComparisonError(selfBlock.RubyContext, result, item); } compareResult = Protocols.ConvertCompareResult(lessThanStorage, greaterThanStorage, blockResult); } else { compareResult = Protocols.Compare(compareStorage, lessThanStorage, greaterThanStorage, result, item); } // Check if we have found the new minimum or maximum (-1 to select max, 1 to select min) if (compareResult == comparisonValue) { result = item; } return null; })); return result; }
public static object Inject(CallSiteStorage<EachSite>/*!*/ each, BlockParam operation, object self, [Optional]object initial) { object result = initial; Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (result == Missing.Value) { result = item; return null; } if (operation == null) { throw RubyExceptions.NoBlockGiven(); } if (operation.Yield(result, item, out result)) { return result; } return null; })); return result != Missing.Value ? result : null; }
public static RubyArray Grep(CallSiteStorage<EachSite>/*!*/ each, BinaryOpStorage/*!*/ caseEquals, BlockParam action, object self, object pattern) { RubyArray result = new RubyArray(); var site = caseEquals.GetCallSite("==="); Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (RubyOps.IsTrue(site.Target(site, pattern, item))) { if (action != null) { if (action.Yield(item, out item)) { return item; } } result.Add(item); } return null; })); return result; }
private static RubyArray/*!*/ Filter(CallSiteStorage<EachSite>/*!*/ each, BlockParam predicate, object self, bool acceptingValue) { RubyArray result = new RubyArray(); Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (predicate == null) { throw RubyExceptions.NoBlockGiven(); } object blockResult; if (predicate.Yield(item, out blockResult)) { return blockResult; } // Check if the result is what we expect (use true to select, false to reject) if (Protocols.IsTrue(blockResult) == acceptingValue) { result.Add(item); } return null; })); return result; }
public static object InvokeOpenBlock(UnaryOpStorage/*!*/ closeStorage, BlockParam block, object obj) { object result = obj; if (!RubyOps.IsRetrySingleton(obj) && block != null) { try { block.Yield(obj, out result); } finally { try { var site = closeStorage.GetCallSite("close"); site.Target(site, obj); } catch (SystemException) { // MRI: nop } } } return result; }
internal static object TryInvokeOpenBlock(RubyContext/*!*/ context, BlockParam/*!*/ block, RubyIO/*!*/ io) { if (block == null) return io; using (io) { object result; block.Yield(io, out result); return result; } }
public static object EachByte(BlockParam block, RubyIO/*!*/ self) { self.RequireReadable(); object aByte; while ((aByte = Getc(self)) != null) { if (block == null) { throw RubyExceptions.NoBlockGiven(); } object result; if (block.Yield((int)aByte, out result)) { return result; } } return self; }
// returns true if block jumped // "result" will be null if there is no successful match private static bool BlockReplaceFirst(RubyScope/*!*/ scope, MutableString/*!*/ input, BlockParam/*!*/ block, RubyRegex/*!*/ pattern, out object blockResult, out MutableString result) { var matchScope = scope.GetInnerMostClosureScope(); MatchData match = RegexpOps.Match(scope, pattern, input); if (match == null || !match.Success) { result = null; blockResult = null; matchScope.CurrentMatch = null; return false; } // copy upfront so that no modifications to the input string are included in the result: result = input.Clone(); matchScope.CurrentMatch = match; if (block.Yield(MutableString.Create(match.Value), out blockResult)) { return true; } // resets the $~ scope variable to the last match (skipd if block jumped): matchScope.CurrentMatch = match; MutableString replacement = Protocols.ConvertToString(scope.RubyContext, blockResult); result.TaintBy(replacement); // Note - we don't interpolate special sequences like \1 in block return value result.Replace(match.Index, match.Length, replacement); blockResult = null; return false; }
public static RubyArray/*!*/ Zip(CallSiteStorage<EachSite>/*!*/ each, ConversionStorage<IList>/*!*/ tryToA, BlockParam block, object self, [NotNull]params object[] args) { RubyArray results = (block == null) ? new RubyArray() : null; // Call to_a on each argument IList[] otherArrays = new IList[args.Length]; for (int i = 0; i < args.Length; i++) { otherArrays[i] = Protocols.TryConvertToArray(tryToA, args[i]); } int index = 0; Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { // Collect items RubyArray array = new RubyArray(otherArrays.Length + 1); array.Add(item); foreach (IList otherArray in otherArrays) { if (index < otherArray.Count) { array.Add(otherArray[index]); } else { array.Add(null); } } index += 1; if (block != null) { object blockResult; if (block.Yield(array, out blockResult)) { return blockResult; } } else { results.Add(array); } return null; })); return results; }
// returns true if block jumped // "result" will be null if there is no successful match private static bool BlockReplaceAll(RubyScope/*!*/ scope, MutableString/*!*/ input, BlockParam/*!*/ block, RubyRegex/*!*/ regex, out object blockResult, out MutableString result) { var matchScope = scope.GetInnerMostClosureScope(); MatchCollection matches = regex.Matches(input); if (matches.Count == 0) { result = null; blockResult = null; matchScope.CurrentMatch = null; return false; } // create an empty result: result = input.CreateInstance().TaintBy(input); int offset = 0; foreach (Match match in matches) { MatchData currentMatch = new MatchData(match, input); matchScope.CurrentMatch = currentMatch; uint version = input.Version; if (block.Yield(MutableString.Create(match.Value), out blockResult)) { return true; } if (input.Version != version) { return false; } // resets the $~ scope variable to the last match (skipd if block jumped): matchScope.CurrentMatch = currentMatch; MutableString replacement = Protocols.ConvertToString(scope.RubyContext, blockResult); result.TaintBy(replacement); // prematch: result.Append(input, offset, match.Index - offset); // replacement (unlike ReplaceAll, don't interpolate special sequences like \1 in block return value): result.Append(replacement); offset = match.Index + match.Length; } // post-last-match: result.Append(input, offset, input.Length - offset); blockResult = null; return false; }
public static object EachWithIndex(CallSiteStorage<EachSite>/*!*/ each, BlockParam/*!*/ block, object self) { // for some reason each_with_index always checks for a block, even if there's nothing to yield if (block == null) { throw RubyExceptions.NoBlockGiven(); } int index = 0; Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { object blockResult; if (block.Yield(item, index, out blockResult)) { return blockResult; } index += 1; return null; })); return self; }
public static object Find(CallSiteStorage<EachSite>/*!*/ each, CallSiteStorage<Func<CallSite, object, object>>/*!*/ callStorage, BlockParam predicate, object self, [Optional]object ifNone) { object result = Missing.Value; Each(each, self, Proc.Create(each.Context, delegate(BlockParam/*!*/ selfBlock, object _, object item) { if (predicate == null) { throw RubyExceptions.NoBlockGiven(); } object blockResult; if (predicate.Yield(item, out blockResult)) { result = blockResult; return selfBlock.Break(blockResult); } if (Protocols.IsTrue(blockResult)) { result = item; return selfBlock.Break(item); } return null; })); if (result == Missing.Value) { if (ifNone == Missing.Value || ifNone == null) { return null; } var site = callStorage.GetCallSite("call", 0); result = site.Target(site, ifNone); } return result; }
public static object Each(RubyContext/*!*/ context, BlockParam block, RubyIO/*!*/ self, [DefaultProtocol]MutableString separator, [DefaultProtocol]int limit) { self.RequireReadable(); MutableString line; while ((line = self.ReadLineOrParagraph(separator, limit)) != null) { if (block == null) { throw RubyExceptions.NoBlockGiven(); } line.IsTainted = true; context.InputProvider.LastInputLineNumber = ++self.LineNumber; object result; if (block.Yield(line, out result)) { return result; } } return self; }