/// <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; }