Beispiel #1
0
 public CapturedToFrameSymbolReplacement(
     LambdaCapturedVariable hoistedField,
     bool isReusable
     ) : base(isReusable)
 {
     this.HoistedField = hoistedField;
 }
Beispiel #2
0
        /// <summary>
        /// Create the frame types.
        /// </summary>
        private void MakeFrames()
        {
            NamedTypeSymbol containingType = this.ContainingType;

            foreach (Symbol captured in analysis.variablesCaptured)
            {
                BoundNode node;
                if (!analysis.variableBlock.TryGetValue(captured, out node) ||
                    analysis.declaredInsideExpressionLambda.Contains(captured))
                {
                    continue;
                }

                LambdaFrame frame;
                if (!frames.TryGetValue(node, out frame))
                {
                    frame = new LambdaFrame(topLevelMethod, CompilationState);
                    frames.Add(node, frame);

                    if (CompilationState.Emitting)
                    {
                        CompilationState.ModuleBuilderOpt.AddSynthesizedDefinition(containingType, frame);
                    }
                }

                SynthesizedFieldSymbolBase proxy = new LambdaCapturedVariable(frame, captured);
                proxies.Add(captured, new CapturedToFrameSymbolReplacement(proxy));
                if (CompilationState.Emitting)
                {
                    CompilationState.ModuleBuilderOpt.AddSynthesizedDefinition(frame, proxy);
                }

                if (proxy.Type.IsRestrictedType())
                {
                    foreach (CSharpSyntaxNode syntax in analysis.capturedSyntax[captured])
                    {
                        // CS4013: Instance of type '{0}' cannot be used inside an anonymous function, query expression, iterator block or async method
                        this.Diagnostics.Add(ErrorCode.ERR_SpecialByRefInLambda, syntax.Location, proxy.Type);
                    }
                }
            }
        }
 internal void AddHoistedField(LambdaCapturedVariable captured) => _membersBuilder.Add(captured);
Beispiel #4
0
 public CapturedToFrameSymbolReplacement(LambdaCapturedVariable hoistedField, bool isReusable)
     : base(isReusable)
 {
     this.HoistedField = hoistedField;
 }
Beispiel #5
0
        /// <summary>
        /// Introduce a frame around the translation of the given node.
        /// </summary>
        /// <param name="node">The node whose translation should be translated to contain a frame</param>
        /// <param name="frame">The frame for the translated node</param>
        /// <param name="F">A function that computes the translation of the node.  It receives lists of added statements and added symbols</param>
        /// <returns>The translated statement, as returned from F</returns>
        private T IntroduceFrame <T>(BoundNode node, LambdaFrame frame, Func <ArrayBuilder <BoundExpression>, ArrayBuilder <LocalSymbol>, T> F)
        {
            NamedTypeSymbol frameType    = frame.ConstructIfGeneric(StaticCast <TypeSymbol> .From(currentTypeParameters));
            LocalSymbol     framePointer = new LambdaFrameLocalSymbol(this.topLevelMethod, frameType, CompilationState);

            CSharpSyntaxNode syntax = node.Syntax;

            // assign new frame to the frame variable
            CompilationState.AddSynthesizedMethod(frame.Constructor, FlowAnalysisPass.AppendImplicitReturn(MethodCompiler.BindMethodBody(frame.Constructor, CompilationState, null), frame.Constructor));

            var prologue = ArrayBuilder <BoundExpression> .GetInstance();

            MethodSymbol constructor = frame.Constructor.AsMember(frameType);

            Debug.Assert(frameType == constructor.ContainingType);
            var newFrame = new BoundObjectCreationExpression(
                syntax: syntax,
                constructor: constructor);

            prologue.Add(new BoundAssignmentOperator(syntax,
                                                     new BoundLocal(syntax, framePointer, null, frameType),
                                                     newFrame,
                                                     frameType));

            CapturedSymbolReplacement oldInnermostFrameProxy = null;

            if ((object)innermostFramePointer != null)
            {
                proxies.TryGetValue(innermostFramePointer, out oldInnermostFrameProxy);
                if (analysis.needsParentFrame.Contains(node))
                {
                    var             capturedFrame = new LambdaCapturedVariable(frame, innermostFramePointer);
                    FieldSymbol     frameParent   = capturedFrame.AsMember(frameType);
                    BoundExpression left          = new BoundFieldAccess(syntax, new BoundLocal(syntax, framePointer, null, frameType), frameParent, null);
                    BoundExpression right         = FrameOfType(syntax, frameParent.Type as NamedTypeSymbol);
                    BoundExpression assignment    = new BoundAssignmentOperator(syntax, left, right, left.Type);

                    if (this.currentMethod.MethodKind == MethodKind.Constructor && capturedFrame.Type == this.currentMethod.ContainingType && !this.seenBaseCall)
                    {
                        // Containing method is a constructor
                        // Initialization statement for the "this" proxy must be inserted
                        // after the constructor initializer statement block
                        // This insertion will be done by the delegate F
                        Debug.Assert(thisProxyInitDeferred == null);
                        thisProxyInitDeferred = assignment;
                    }
                    else
                    {
                        prologue.Add(assignment);
                    }

                    if (CompilationState.Emitting)
                    {
                        CompilationState.ModuleBuilderOpt.AddSynthesizedDefinition(frame, capturedFrame);
                    }

                    proxies[innermostFramePointer] = new CapturedToFrameSymbolReplacement(capturedFrame);
                }
            }

            // Capture any parameters of this block.  This would typically occur
            // at the top level of a method or lambda with captured parameters.
            // TODO: speed up the following by computing it in analysis.
            foreach (var v in analysis.variablesCaptured)
            {
                BoundNode varNode;
                if (!analysis.variableBlock.TryGetValue(v, out varNode) ||
                    varNode != node ||
                    analysis.declaredInsideExpressionLambda.Contains(v))
                {
                    continue;
                }

                InitVariableProxy(syntax, v, framePointer, prologue);
            }

            Symbol oldInnermostFramePointer = innermostFramePointer;

            innermostFramePointer = framePointer;
            var addedLocals = ArrayBuilder <LocalSymbol> .GetInstance();

            addedLocals.Add(framePointer);
            framePointers.Add(frame, framePointer);

            var result = F(prologue, addedLocals);

            framePointers.Remove(frame);
            innermostFramePointer = oldInnermostFramePointer;

            if ((object)innermostFramePointer != null)
            {
                if (oldInnermostFrameProxy != null)
                {
                    proxies[innermostFramePointer] = oldInnermostFrameProxy;
                }
                else
                {
                    proxies.Remove(innermostFramePointer);
                }
            }

            return(result);
        }