public override BoundNode VisitBaseReference(BoundBaseReference node) { // TODO: fix up the type of the resulting node to be the base type CapturedSymbolReplacement proxy = proxies[this.originalMethod.ThisParameter]; Debug.Assert(proxy != null); return(proxy.Replacement(F.Syntax, frameType => F.This())); }
protected BoundStatement CacheThisIfNeeded() { // restore "this" cache, if there is a cache if ((object)this.cachedThis != null) { CapturedSymbolReplacement proxy = proxies[this.OriginalMethod.ThisParameter]; var fetchThis = proxy.Replacement(F.Syntax, frameType => F.This()); return(F.Assignment(F.Local(this.cachedThis), fetchThis)); } // do nothing return(F.StatementList()); }
public override BoundNode VisitBaseReference(BoundBaseReference node) { // TODO: fix up the type of the resulting node to be the base type // if "this" is cached, return it. if ((object)this.cachedThis != null) { return(F.Local(this.cachedThis)); } CapturedSymbolReplacement proxy = proxies[this.OriginalMethod.ThisParameter]; Debug.Assert(proxy != null); return(proxy.Replacement(F.Syntax, frameType => F.This())); }
/// <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); }