Create() public method

Creates a copy of the proc that has the same target, context and self object as this block.
public Create ( Proc proc ) : Proc
proc Proc
return Proc
Ejemplo n.º 1
0
        public static Proc /*!*/ CreateNew(RubyClass /*!*/ self, Proc /*!*/ proc)
        {
            Assert.NotNull(self, proc);

            // an instance of Proc class, the identity is preserved:
            if (self.GetUnderlyingSystemType() == typeof(Proc))
            {
                return(proc);
            }

            // an instance of a Proc subclass:
            var result = new Proc.Subclass(self, proc);

            // a call to the initializer with a block:
            object initResult = null;

            do
            {
                // a new proc is created each iteration (even if a subclass is passed in, the Proc class is created):
                var argProc = proc.Create(proc);

                try {
                    initResult = _InitializeSite.Target(_InitializeSite, self.Context, proc, argProc);
                } catch (EvalUnwinder u) {
                    initResult = u.ReturnValue;
                }

                Debug.Assert(proc != argProc, "retry doesn't propagate to the caller");
            } while (RubyOps.IsRetrySingleton(initResult));

            return(result);
        }
Ejemplo n.º 2
0
        private static RubyArray /*!*/ Filter(RubyContext /*!*/ context, BlockParam predicate, object self, bool acceptingValue)
        {
            RubyArray result = new RubyArray();

            Each(context, self, Proc.Create(context, delegate(BlockParam /*!*/ selfBlock, 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);
        }
Ejemplo n.º 3
0
        private static object TrueForItems(CallSiteStorage <EachSite> /*!*/ each, BlockParam predicate, object self, bool expected)
        {
            object result = ScriptingRuntimeHelpers.BooleanToObject(expected);

            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 != expected)
                {
                    result = ScriptingRuntimeHelpers.BooleanToObject(!expected);
                    return(selfBlock.Break(result));
                }

                return(null);
            }));

            return(result);
        }
Ejemplo n.º 4
0
        private static object GetExtreme(CallSiteStorage <EachSite> /*!*/ each, ComparisonStorage /*!*/ comparisonStorage, 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) {
                if (firstItem)
                {
                    result    = item;
                    firstItem = false;
                    return(null);
                }

                object blockResult;
                int?compareResult = CompareItems(comparisonStorage, item, result, comparer, out blockResult);
                if (compareResult == null)
                {
                    result = blockResult;
                    return(selfBlock.PropagateFlow(comparer, blockResult));
                }

                // 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);
        }
Ejemplo n.º 5
0
        public static object FindIndex(CallSiteStorage <EachSite> /*!*/ each, [NotNull] BlockParam /*!*/ predicate, object self)
        {
            int index = 0;

            object result = null;

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                object blockResult;
                if (predicate.Yield(item, out blockResult))
                {
                    result = blockResult;
                    return(selfBlock.PropagateFlow(predicate, blockResult));
                }

                if (Protocols.IsTrue(blockResult))
                {
                    result = ScriptingRuntimeHelpers.Int32ToObject(index);
                    return(selfBlock.Break(null));
                }

                index++;
                return(null);
            }));

            return(result);
        }
Ejemplo n.º 6
0
        public static object Partition(CallSiteStorage <EachSite> /*!*/ each, [NotNull] BlockParam /*!*/ predicate, object self)
        {
            RubyArray trueSet  = new RubyArray();
            RubyArray falseSet = new RubyArray();
            RubyArray pair     = new RubyArray(2);

            pair.Add(trueSet);
            pair.Add(falseSet);
            object result = pair;

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                object blockResult;
                if (predicate.Yield(item, out blockResult))
                {
                    result = blockResult;
                    return(selfBlock.PropagateFlow(predicate, blockResult));
                }

                if (Protocols.IsTrue(blockResult))
                {
                    trueSet.Add(item);
                }
                else
                {
                    falseSet.Add(item);
                }

                return(null);
            }));

            return(result);
        }
Ejemplo n.º 7
0
        public static object Find(CallSiteStorage <EachSite> /*!*/ each, CallSiteStorage <Func <CallSite, object, object> > /*!*/ callStorage,
                                  [NotNull] BlockParam /*!*/ predicate, object self, [Optional] object ifNone)
        {
            object result = Missing.Value;

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                object blockResult;
                if (predicate.Yield(item, out blockResult))
                {
                    result = blockResult;
                    return(selfBlock.PropagateFlow(predicate, 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);
        }
Ejemplo n.º 8
0
        public static object TakeWhile(CallSiteStorage <EachSite> /*!*/ each, [NotNull] BlockParam /*!*/ predicate, object self)
        {
            RubyArray resultArray = new RubyArray();

            object result = resultArray;

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                object blockResult;
                if (predicate.Yield(item, out blockResult))
                {
                    result = blockResult;
                    return(selfBlock.PropagateFlow(predicate, blockResult));
                }

                if (Protocols.IsTrue(blockResult))
                {
                    resultArray.Add(item);
                }
                else
                {
                    selfBlock.Break(null);
                }

                return(null);
            }));

            return(result);
        }
Ejemplo n.º 9
0
        private static object Filter(CallSiteStorage <EachSite> /*!*/ each, BlockParam predicate, object self, bool acceptingValue)
        {
            RubyArray resultArray = new RubyArray();
            object    result      = resultArray;

            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.PropagateFlow(predicate, blockResult));
                }

                // Check if the result is what we expect (use true to select, false to reject)
                if (Protocols.IsTrue(blockResult) == acceptingValue)
                {
                    resultArray.Add(item);
                }
                return(null);
            }));

            return(result);
        }
Ejemplo n.º 10
0
        private static object TrueForItems(RubyContext /*!*/ context, BlockParam predicate, object self, bool expected)
        {
            bool result = expected;

            Each(context, self, Proc.Create(context, delegate(BlockParam /*!*/ selfBlock, 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));
        }
Ejemplo n.º 11
0
        public static RubyArray /*!*/ Partition(RubyContext /*!*/ context, BlockParam predicate, object self)
        {
            RubyArray trueSet  = new RubyArray();
            RubyArray falseSet = new RubyArray();

            Each(context, self, Proc.Create(context, delegate(BlockParam /*!*/ selfBlock, 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);
        }
Ejemplo n.º 12
0
        public static object Grep(CallSiteStorage <EachSite> /*!*/ each, BinaryOpStorage /*!*/ caseEquals,
                                  BlockParam action, object self, object pattern)
        {
            RubyArray resultArray = new RubyArray();
            object    result      = resultArray;
            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))
                        {
                            result = item;
                            return(selfBlock.PropagateFlow(action, item));
                        }
                    }
                    resultArray.Add(item);
                }
                return(null);
            }));

            return(result);
        }
Ejemplo n.º 13
0
        public static object Inject(RubyContext /*!*/ context, BlockParam operation, object self, [Optional] object initial)
        {
            object result = initial;

            Each(context, self, Proc.Create(context, delegate(BlockParam /*!*/ selfBlock, 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);
        }
Ejemplo n.º 14
0
        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(selfBlock.PropagateFlow(operation, result));
                }

                return(null);
            }));

            return(result != Missing.Value ? result : null);
        }
Ejemplo n.º 15
0
        public static RubyArray /*!*/ Take(CallSiteStorage <EachSite> /*!*/ each, object self, [DefaultProtocol] int count)
        {
            if (count < 0)
            {
                throw RubyExceptions.CreateArgumentError("attempt to take negative size");
            }

            var result = new RubyArray(count);

            if (count == 0)
            {
                return(result);
            }

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                result.Add(item);
                if (--count == 0)
                {
                    selfBlock.Break(null);
                }
                return(null);
            }));

            return(result);
        }
Ejemplo n.º 16
0
        public static Hash GroupBy(CallSiteStorage <EachSite> /*!*/ each, [NotNull] BlockParam /*!*/ predicate, object self)
        {
            var grouped = new Dictionary <object, object>();

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                object blockResult;
                if (predicate.Yield(item, out blockResult))
                {
                    return(selfBlock.PropagateFlow(predicate, blockResult));
                }

                RubyArray existingGroup = IDictionaryOps.GetElement(each.Context, grouped, blockResult) as RubyArray;
                if (existingGroup != null)
                {
                    existingGroup.Add(item);
                }
                else
                {
                    IDictionaryOps.SetElement(each.Context, grouped, blockResult, new RubyArray {
                        item
                    });
                }

                return(null);
            }));

            return(new Hash(grouped));
        }
Ejemplo n.º 17
0
        public static object One(CallSiteStorage <EachSite> /*!*/ each, BinaryOpStorage /*!*/ equals, BlockParam comparer, object self)
        {
            int count = 0;

            object result = null;

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                object blockResult;
                if (comparer == null)
                {
                    blockResult = item;
                }
                else if (comparer.Yield(item, out blockResult))
                {
                    count  = -1;
                    result = blockResult;
                    return(selfBlock.PropagateFlow(comparer, blockResult));
                }

                if (Protocols.IsTrue(blockResult) && ++count > 1)
                {
                    selfBlock.Break(null);
                }
                return(null);
            }));

            return((count >= 0) ? ScriptingRuntimeHelpers.BooleanToObject(count == 1) : result);
        }
Ejemplo n.º 18
0
        public static int Count(CallSiteStorage <EachSite> /*!*/ each, object self)
        {
            int result = 0;

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                result++;
                return(null);
            }));
            return(result);
        }
Ejemplo n.º 19
0
        public static Proc /*!*/ ToProc(RubyContext /*!*/ context, RubyMethod /*!*/ self)
        {
            RubyMethodInfo mi = self.Info as RubyMethodInfo;

            if (mi != null)
            {
                return(Proc.Create(context, mi.Method, self.Target, mi.Arity));
            }
            // TODO: figure out what the semantics should be for a set of CLR methods returned ...
            throw new NotImplementedException();
        }
Ejemplo n.º 20
0
        public static RubyArray /*!*/ ToArray(RubyContext /*!*/ context, object self)
        {
            RubyArray data = new RubyArray();

            Each(context, self, Proc.Create(context, delegate(BlockParam /*!*/ selfBlock, object item) {
                data.Add(item);
                return(null);
            }));

            return(data);
        }
Ejemplo n.º 21
0
        public static RubyArray /*!*/ ToArray(CallSiteStorage <EachSite> /*!*/ each, object self)
        {
            RubyArray data = new RubyArray();

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                data.Add(item);
                return(null);
            }));

            return(data);
        }
Ejemplo n.º 22
0
        public static object First(CallSiteStorage <EachSite> /*!*/ each, object self)
        {
            object result = null;

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                result = item;
                selfBlock.Break(null);
                return(null);
            }));
            return(result);
        }
Ejemplo n.º 23
0
        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))
                    {
                        result = blockResult;
                        return(selfBlock.PropagateFlow(comparer, 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);
        }
Ejemplo n.º 24
0
        public static object 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> >();
            object result = null;

            // 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))
                {
                    keyValuePairs = null;
                    result        = key;
                    return(selfBlock.PropagateFlow(keySelector, key));
                }

                keyValuePairs.Add(new KeyValuePair <object, object>(key, item));
                return(null);
            }));

            if (keyValuePairs == null)
            {
                return(result);
            }

            // 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 results = new RubyArray(keyValuePairs.Count);

            foreach (KeyValuePair <object, object> pair in keyValuePairs)
            {
                results.Add(pair.Value);
            }

            return(results);
        }
Ejemplo n.º 25
0
        public static bool Contains(RubyContext /*!*/ context, object self, object value)
        {
            bool result = false;

            Each(context, self, Proc.Create(context, delegate(BlockParam /*!*/ selfBlock, object item) {
                if (Protocols.IsEqual(context, item, value))
                {
                    result = true;
                    return(selfBlock.Break(result));
                }
                return(null);
            }));

            return(result);
        }
Ejemplo n.º 26
0
        public static object Contains(CallSiteStorage <EachSite> /*!*/ each, BinaryOpStorage /*!*/ equals, object self, object value)
        {
            object result = ScriptingRuntimeHelpers.BooleanToObject(false);

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                if (Protocols.IsEqual(equals, item, value))
                {
                    result = ScriptingRuntimeHelpers.BooleanToObject(true);
                    return(selfBlock.Break(result));
                }
                return(null);
            }));

            return(result);
        }
Ejemplo n.º 27
0
        public static RubyArray /*!*/ Zip(RubyContext /*!*/ context, 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.ConvertToArray(context, args[i]);
            }

            int index = 0;

            Each(context, self, Proc.Create(context, delegate(BlockParam /*!*/ selfBlock, 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);
        }
Ejemplo n.º 28
0
        private static object EachSlice(CallSiteStorage <EachSite> /*!*/ each, BlockParam /*!*/ block, object self, int sliceSize,
                                        bool includeIncomplete, Func <RubyArray /*!*/, RubyArray> /*!*/ newSliceFactory)
        {
            if (sliceSize <= 0)
            {
                throw RubyExceptions.CreateArgumentError("invalid slice size");
            }

            RubyArray slice = null;

            object result = null;

            Each(each, self, Proc.Create(each.Context, delegate(BlockParam /*!*/ selfBlock, object _, object item) {
                if (slice == null)
                {
                    slice = new RubyArray(sliceSize);
                }

                slice.Add(item);

                if (slice.Count == sliceSize)
                {
                    var completeSlice = slice;
                    slice             = newSliceFactory(slice);

                    object blockResult;
                    if (block.Yield(completeSlice, out blockResult))
                    {
                        result = blockResult;
                        return(selfBlock.PropagateFlow(block, blockResult));
                    }
                }

                return(null);
            }));

            if (slice != null && includeIncomplete)
            {
                object blockResult;
                if (block.Yield(slice, out blockResult))
                {
                    return(blockResult);
                }
            }

            return(result);
        }
Ejemplo n.º 29
0
        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);
        }
Ejemplo n.º 30
0
        private static object GetExtreme(RubyContext /*!*/ context, BlockParam comparer, object self, int comparisonValue)
        {
            bool   firstItem = true;
            object result    = null;

            Each(context, self, Proc.Create(context, delegate(BlockParam /*!*/ selfBlock, 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(context, result, item);
                    }

                    compareResult = Protocols.ConvertCompareResult(context, blockResult);
                }
                else
                {
                    compareResult = Protocols.Compare(context, 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);
        }
Ejemplo n.º 31
0
        public static Proc/*!*/ CreateNew(CallSiteStorage<Func<CallSite, Proc, Proc, object>>/*!*/ storage,
            RubyClass/*!*/ self, Proc/*!*/ proc) {
            Assert.NotNull(storage, self, proc);

            // an instance of Proc class, the identity is preserved:
            if (self.GetUnderlyingSystemType() == typeof(Proc)) {
                return proc;
            }

            // an instance of a Proc subclass:
            var result = new Proc.Subclass(self, proc);

            var initialize = storage.GetCallSite("initialize", new RubyCallSignature(0, RubyCallFlags.HasImplicitSelf | RubyCallFlags.HasBlock));

            // a call to the initializer with a block:
            object initResult = null;
            do {
                // a new proc is created each iteration (even if a subclass is passed in, the Proc class is created):
                var argProc = proc.Create(proc);

                try {
                    initResult = initialize.Target(initialize, proc, argProc);
                } catch (EvalUnwinder u) {
                    initResult = u.ReturnValue;
                }

                Debug.Assert(proc != argProc, "retry doesn't propagate to the caller");
            } while (RubyOps.IsRetrySingleton(initResult));

            return result;
        }
Ejemplo n.º 32
0
        public static Proc/*!*/ CreateNew(RubyClass/*!*/ self, Proc/*!*/ proc) {
            Assert.NotNull(self, proc);

            // an instance of Proc class, the identity is preserved:
            if (self.GetUnderlyingSystemType() == typeof(Proc)) {
                return proc;
            }

            // an instance of a Proc subclass:
            var result = new Proc.Subclass(self, proc);

            // a call to the initializer with a block:
            object initResult = null;
            do {
                // a new proc is created each iteration (even if a subclass is passed in, the Proc class is created):
                var argProc = proc.Create(proc);

                try {
                    initResult = _InitializeSite.Target(_InitializeSite, self.Context, proc, argProc);
                } catch (EvalUnwinder u) {
                    initResult = u.ReturnValue;
                }

                Debug.Assert(proc != argProc, "retry doesn't propagate to the caller");
            } while (RubyOps.IsRetrySingleton(initResult));

            return result;
        }