Exemple #1
0
        /// <summary>
        /// Visit all references to local functions (calls, delegate
        /// conversions, delegate creations) and rewrite them to point
        /// to the rewritten local function method instead of the original.
        /// </summary>
        public BoundStatement RewriteLocalFunctionReferences(BoundStatement loweredBody)
        {
            var rewriter = new LocalFunctionReferenceRewriter(this);

            Debug.Assert(_currentMethod == _topLevelMethod);

            // Visit the body first since the state is already set
            // for the top-level method
            var newBody = (BoundStatement)rewriter.Visit(loweredBody);

            // Visit all the rewritten methods as well
            var synthesizedMethods = _synthesizedMethods;

            if (synthesizedMethods != null)
            {
                var newMethods = ArrayBuilder <TypeCompilationState.MethodWithBody> .GetInstance(
                    synthesizedMethods.Count);

                foreach (var oldMethod in synthesizedMethods)
                {
                    var synthesizedLambda = oldMethod.Method as SynthesizedLambdaMethod;
                    if (synthesizedLambda == null)
                    {
                        // The only methods synthesized by the rewriter should
                        // be lowered closures and frame constructors
                        Debug.Assert(oldMethod.Method.MethodKind == MethodKind.Constructor ||
                                     oldMethod.Method.MethodKind == MethodKind.StaticConstructor);
                        newMethods.Add(oldMethod);
                        continue;
                    }

                    _currentMethod = synthesizedLambda;
                    var closureKind = synthesizedLambda.ClosureKind;
                    if (closureKind == ClosureKind.Static || closureKind == ClosureKind.Singleton)
                    {
                        // no link from a static lambda to its container
                        _innermostFramePointer = _currentFrameThis = null;
                    }
                    else
                    {
                        _currentFrameThis      = synthesizedLambda.ThisParameter;
                        _innermostFramePointer = null;
                        _framePointers.TryGetValue(synthesizedLambda.ContainingType, out _innermostFramePointer);
                    }

                    var containerAsFrame = synthesizedLambda.ContainingType as LambdaFrame;

                    // Includes type parameters from the containing type iff
                    // the containing type is a frame. If it is a frame then
                    // the type parameters are captured, meaning that the
                    // type parameters should be included.
                    // If it is not a frame then the local function is being
                    // directly lowered into the method's containing type and
                    // the parameters should never be substituted.
                    _currentTypeParameters = containerAsFrame?.TypeParameters.Concat(synthesizedLambda.TypeParameters)
                                             ?? synthesizedLambda.TypeParameters;
                    _currentLambdaBodyTypeMap = synthesizedLambda.TypeMap;

                    var rewrittenBody = (BoundStatement)rewriter.Visit(oldMethod.Body);

                    var newMethod = new TypeCompilationState.MethodWithBody(
                        synthesizedLambda, rewrittenBody, oldMethod.ImportChainOpt);
                    newMethods.Add(newMethod);
                }

                _synthesizedMethods = newMethods;
                synthesizedMethods.Free();
            }

            return(newBody);
        }
        /// <summary>
        /// Visit all references to local functions (calls, delegate
        /// conversions, delegate creations) and rewrite them to point
        /// to the rewritten local function method instead of the original. 
        /// </summary>
        public BoundStatement RewriteLocalFunctionReferences(BoundStatement loweredBody)
        {
            var rewriter = new LocalFunctionReferenceRewriter(this);

            Debug.Assert(_currentMethod == _topLevelMethod);

            // Visit the body first since the state is already set
            // for the top-level method
            var newBody = (BoundStatement)rewriter.Visit(loweredBody);

            // Visit all the rewritten methods as well
            var synthesizedMethods = _synthesizedMethods;
            if (synthesizedMethods != null)
            {
                var newMethods = ArrayBuilder<TypeCompilationState.MethodWithBody>.GetInstance(
                    synthesizedMethods.Count);

                foreach (var oldMethod in synthesizedMethods)
                {
                    var synthesizedLambda = oldMethod.Method as SynthesizedLambdaMethod;
                    if (synthesizedLambda == null)
                    {
                        // The only methods synthesized by the rewriter should
                        // be lowered closures and frame constructors
                        Debug.Assert(oldMethod.Method.MethodKind == MethodKind.Constructor ||
                                     oldMethod.Method.MethodKind == MethodKind.StaticConstructor);
                        newMethods.Add(oldMethod);
                        continue;
                    }

                    _currentMethod = synthesizedLambda;
                    var closureKind = synthesizedLambda.ClosureKind;
                    if (closureKind == ClosureKind.Static || closureKind == ClosureKind.Singleton)
                    {
                        // no link from a static lambda to its container
                        _innermostFramePointer = _currentFrameThis = null;
                    }
                    else
                    {
                        _currentFrameThis = synthesizedLambda.ThisParameter;
                        _innermostFramePointer = null;
                        _framePointers.TryGetValue(synthesizedLambda.ContainingType, out _innermostFramePointer);
                    }

                    var containerAsFrame = synthesizedLambda.ContainingType as LambdaFrame;

                    // Includes type parameters from the containing type iff
                    // the containing type is a frame. If it is a frame then
                    // the type parameters are captured, meaning that the
                    // type parameters should be included.
                    // If it is not a frame then the local function is being
                    // directly lowered into the method's containing type and
                    // the parameters should never be substituted.
                    _currentTypeParameters = containerAsFrame?.TypeParameters.Concat(synthesizedLambda.TypeParameters)
                        ?? synthesizedLambda.TypeParameters;
                    _currentLambdaBodyTypeMap = synthesizedLambda.TypeMap;

                    var rewrittenBody = (BoundStatement)rewriter.Visit(oldMethod.Body);

                    var newMethod = new TypeCompilationState.MethodWithBody(
                        synthesizedLambda, rewrittenBody, oldMethod.ImportChainOpt);
                    newMethods.Add(newMethod);
                }

                _synthesizedMethods = newMethods;
                synthesizedMethods.Free();
            }

            return newBody;
        }