private BoundNode VisitLambdaOrFunction(IBoundLambdaOrFunction node) { Debug.Assert((object)node.Symbol != null); SeenLambda = true; var oldParent = _currentParent; var oldBlock = _currentScope; _currentParent = node.Symbol; _currentScope = node.Body; ScopeParent[_currentScope] = oldBlock; ScopeOwner.Add(_currentScope, _currentParent); var wasInExpressionLambda = _inExpressionLambda; _inExpressionLambda = _inExpressionLambda || ((node as BoundLambda)?.Type.IsExpressionTree() ?? false); if (!_inExpressionLambda) { // for the purpose of constructing frames parameters are scoped as if they are inside the lambda block foreach (var parameter in node.Symbol.Parameters) { VariableScope[parameter] = _currentScope; } foreach (var local in node.Body.Locals) { VariableScope[local] = _currentScope; } } var result = base.VisitBlock(node.Body); _inExpressionLambda = wasInExpressionLambda; _currentParent = oldParent; _currentScope = oldBlock; return(result); }
internal SynthesizedLambdaMethod( NamedTypeSymbol containingType, ImmutableArray<TypeSymbol> structClosures, ClosureKind closureKind, MethodSymbol topLevelMethod, DebugId topLevelMethodId, IBoundLambdaOrFunction lambdaNode, DebugId lambdaId) : base(containingType, lambdaNode.Symbol, null, lambdaNode.Syntax.SyntaxTree.GetReference(lambdaNode.Body.Syntax), lambdaNode.Syntax.GetLocation(), lambdaNode is BoundLocalFunctionStatement ? MakeName(topLevelMethod.Name, lambdaNode.Symbol.Name, topLevelMethodId, closureKind, lambdaId) : MakeName(topLevelMethod.Name, topLevelMethodId, closureKind, lambdaId), (closureKind == ClosureKind.ThisOnly ? DeclarationModifiers.Private : DeclarationModifiers.Internal) | (closureKind == ClosureKind.Static ? DeclarationModifiers.Static : 0) | (lambdaNode.Symbol.IsAsync ? DeclarationModifiers.Async : 0)) { _topLevelMethod = topLevelMethod; TypeMap typeMap; ImmutableArray<TypeParameterSymbol> typeParameters; ImmutableArray<TypeParameterSymbol> constructedFromTypeParameters; LambdaFrame lambdaFrame; lambdaFrame = this.ContainingType as LambdaFrame; switch (closureKind) { case ClosureKind.Singleton: // all type parameters on method (except the top level method's) case ClosureKind.General: // only lambda's type parameters on method (rest on class) Debug.Assert(lambdaFrame != null); typeMap = lambdaFrame.TypeMap.WithConcatAlphaRename(lambdaNode.Symbol, this, out typeParameters, out constructedFromTypeParameters, lambdaFrame.ContainingMethod); break; case ClosureKind.ThisOnly: // all type parameters on method case ClosureKind.Static: Debug.Assert(lambdaFrame == null); typeMap = TypeMap.Empty.WithConcatAlphaRename(lambdaNode.Symbol, this, out typeParameters, out constructedFromTypeParameters, null); break; default: throw ExceptionUtilities.Unreachable; } if (!structClosures.IsDefaultOrEmpty && typeParameters.Length != 0) { var constructedStructClosures = ArrayBuilder<TypeSymbol>.GetInstance(); foreach (var closure in structClosures) { var frame = (LambdaFrame)closure; NamedTypeSymbol constructed; if (frame.Arity == 0) { constructed = frame; } else { var originals = frame.ConstructedFromTypeParameters; var newArgs = typeMap.SubstituteTypeParameters(originals); constructed = frame.Construct(newArgs); } constructedStructClosures.Add(constructed); } structClosures = constructedStructClosures.ToImmutableAndFree(); } _structClosures = structClosures; AssignTypeMapAndTypeParameters(typeMap, typeParameters); }
private BoundNode VisitLambdaOrFunction(IBoundLambdaOrFunction node) { Debug.Assert((object)node.Symbol != null); SeenLambda = true; var oldParent = _currentParent; var oldBlock = _currentScope; _currentParent = node.Symbol; _currentScope = node.Body; ScopeParent[_currentScope] = oldBlock; ScopeOwner.Add(_currentScope, _currentParent); var wasInExpressionLambda = _inExpressionLambda; _inExpressionLambda = _inExpressionLambda || ((node as BoundLambda)?.Type.IsExpressionTree() ?? false); if (!_inExpressionLambda) { // for the purpose of constructing frames parameters are scoped as if they are inside the lambda block foreach (var parameter in node.Symbol.Parameters) { VariableScope[parameter] = _currentScope; } foreach (var local in node.Body.Locals) { VariableScope[local] = _currentScope; } } var result = base.VisitBlock(node.Body); _inExpressionLambda = wasInExpressionLambda; _currentParent = oldParent; _currentScope = oldBlock; return result; }
internal SynthesizedLambdaMethod( NamedTypeSymbol containingType, ImmutableArray <TypeSymbol> structClosures, ClosureKind closureKind, MethodSymbol topLevelMethod, DebugId topLevelMethodId, IBoundLambdaOrFunction lambdaNode, DebugId lambdaId) : base(containingType, lambdaNode.Symbol, null, lambdaNode.Syntax.SyntaxTree.GetReference(lambdaNode.Body.Syntax), lambdaNode.Syntax.GetLocation(), lambdaNode is BoundLocalFunctionStatement ? MakeName(topLevelMethod.Name, lambdaNode.Symbol.Name, topLevelMethodId, closureKind, lambdaId) : MakeName(topLevelMethod.Name, topLevelMethodId, closureKind, lambdaId), (closureKind == ClosureKind.ThisOnly ? DeclarationModifiers.Private : DeclarationModifiers.Internal) | (closureKind == ClosureKind.Static ? DeclarationModifiers.Static : 0) | (lambdaNode.Symbol.IsAsync ? DeclarationModifiers.Async : 0)) { _topLevelMethod = topLevelMethod; ClosureKind = closureKind; TypeMap typeMap; ImmutableArray <TypeParameterSymbol> typeParameters; ImmutableArray <TypeParameterSymbol> constructedFromTypeParameters; LambdaFrame lambdaFrame; lambdaFrame = this.ContainingType as LambdaFrame; switch (closureKind) { case ClosureKind.Singleton: // all type parameters on method (except the top level method's) case ClosureKind.General: // only lambda's type parameters on method (rest on class) Debug.Assert(lambdaFrame != null); typeMap = lambdaFrame.TypeMap.WithConcatAlphaRename(lambdaNode.Symbol, this, out typeParameters, out constructedFromTypeParameters, lambdaFrame.ContainingMethod); break; case ClosureKind.ThisOnly: // all type parameters on method case ClosureKind.Static: Debug.Assert(lambdaFrame == null); typeMap = TypeMap.Empty.WithConcatAlphaRename(lambdaNode.Symbol, this, out typeParameters, out constructedFromTypeParameters, null); break; default: throw ExceptionUtilities.Unreachable; } if (!structClosures.IsDefaultOrEmpty && typeParameters.Length != 0) { var constructedStructClosures = ArrayBuilder <TypeSymbol> .GetInstance(); foreach (var closure in structClosures) { var frame = (LambdaFrame)closure; NamedTypeSymbol constructed; if (frame.Arity == 0) { constructed = frame; } else { var originals = frame.ConstructedFromTypeParameters; var newArgs = typeMap.SubstituteTypeParameters(originals); constructed = frame.Construct(newArgs); } constructedStructClosures.Add(constructed); } structClosures = constructedStructClosures.ToImmutableAndFree(); } _structClosures = structClosures; AssignTypeMapAndTypeParameters(typeMap, typeParameters); }