/// <summary> /// Rewrite the given node to eliminate lambda expressions. Also returned are the method symbols and their /// bound bodies for the extracted lambda bodies. These would typically be emitted by the caller such as /// MethodBodyCompiler. See this class' documentation /// for a more thorough explanation of the algorithm and its use by clients. /// </summary> /// <param name="node">The bound node to be rewritten</param> /// <param name="thisType">The type of the top-most frame</param> /// <param name="thisParameter">The "this" parameter in the top-most frame, or null if static method</param> /// <param name="method">The containing method of the node to be rewritten</param> /// <param name="compilationState">The caller's buffer into which we produce additional methods to be emitted by the caller</param> /// <param name="diagnostics">Diagnostic bag for diagnostics</param> /// <param name="analysis">A caller-provided analysis of the node's lambdas</param> /// <param name="generateDebugInfo"></param> /// <param name="assignLocals">The rewritten tree should include assignments of the original locals to the lifted proxies</param> public static BoundStatement Rewrite( BoundStatement node, NamedTypeSymbol thisType, ParameterSymbol thisParameter, MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, Analysis analysis, bool generateDebugInfo, bool assignLocals = false) { Debug.Assert((object)thisType != null); Debug.Assert(((object)thisParameter == null) || (thisParameter.Type == thisType)); CheckLocalsDefined(node); var rewriter = new LambdaRewriter( analysis, thisType, thisParameter, method, compilationState, diagnostics, generateDebugInfo, assignLocals); analysis.ComputeLambdaScopesAndFrameCaptures(); rewriter.MakeFrames(); var body = rewriter.AddStatementsIfNeeded((BoundStatement)rewriter.Visit(node)); CheckLocalsDefined(body); return(body); }
public LocalFunctionReferenceRewriter(LambdaRewriter lambdaRewriter) { _lambdaRewriter = lambdaRewriter; }
internal static BoundStatement LowerStatement( bool generateDebugInfo, MethodSymbol method, BoundStatement body, SynthesizedSubmissionFields previousSubmissionFields, TypeCompilationState compilationState, DiagnosticBag diagnostics) { if (body.HasErrors) { return(body); } bool sawLambdas; bool sawDynamicOperations; bool sawAwaitInExceptionHandler; var loweredBody = LocalRewriter.Rewrite( method.DeclaringCompilation, generateDebugInfo, method, method.ContainingType, body, compilationState, diagnostics, previousSubmissionFields, out sawLambdas, out sawDynamicOperations, out sawAwaitInExceptionHandler); if (sawDynamicOperations && compilationState.ModuleBuilder.IsENCDelta) { // Dynamic operations are not supported in ENC. var location = method.Locations[0]; diagnostics.Add(new CSDiagnosticInfo(ErrorCode.ERR_EnCNoDynamicOperation), location); } if (loweredBody.HasErrors) { return(loweredBody); } if (sawAwaitInExceptionHandler) { // If we have awaits in handlers, we need to // replace handlers with synthetic ones which can be consumed by async rewriter. // The reason why this rewrite happens before the lambda rewrite // is that we may need access to exception locals and it would be fairly hard to do // if these locals are captured into closures (possibly nested ones). Debug.Assert(method.IteratorElementType == null); loweredBody = AsyncHandlerRewriter.Rewrite( generateDebugInfo, method, method.ContainingType, loweredBody, compilationState, diagnostics); } if (loweredBody.HasErrors) { return(loweredBody); } BoundStatement bodyWithoutLambdas = loweredBody; if (sawLambdas) { LambdaRewriter.Analysis lambdaAnalysis = LambdaRewriter.Analysis.Analyze(loweredBody, method, out sawLambdas); if (sawLambdas) { bodyWithoutLambdas = LambdaRewriter.Rewrite(loweredBody, method.ContainingType, method.ThisParameter, method, compilationState, diagnostics, lambdaAnalysis, generateDebugInfo); } } if (bodyWithoutLambdas.HasErrors) { return(bodyWithoutLambdas); } BoundStatement bodyWithoutIterators = IteratorRewriter.Rewrite(bodyWithoutLambdas, method, compilationState, diagnostics, generateDebugInfo); if (bodyWithoutIterators.HasErrors) { return(bodyWithoutIterators); } BoundStatement bodyWithoutAsync = AsyncRewriter2.Rewrite(bodyWithoutIterators, method, compilationState, diagnostics, generateDebugInfo); return(bodyWithoutAsync); }