Exemplo n.º 1
0
        private BoundNode BindFunctionDefinition(FunctionDefinitionSyntax declaration, Symbol parent)
        {
            BindAttributes(declaration.Attributes);

            var boundReturnType = Bind(declaration.ReturnType, x => BindType(x, parent));

            var isQualifiedName = false;

            ContainerSymbol containerSymbol;
            Symbol functionOwner;
            switch (declaration.Name.Kind)
            {
                case SyntaxKind.IdentifierDeclarationName:
                    containerSymbol = null;
                    functionOwner = parent;
                    break;
                case SyntaxKind.QualifiedDeclarationName:
                    containerSymbol = LookupContainer(((QualifiedDeclarationNameSyntax) declaration.Name).Left);
                    if (containerSymbol == null)
                        return new BoundErrorNode();
                    isQualifiedName = true;
                    functionOwner = containerSymbol;
                    break;
                default:
                    throw new InvalidOperationException();
            }

            var containerBinder = containerSymbol?.Binder ?? this;

            var symbolTable = containerBinder.LocalSymbols;

            var functionSymbol = symbolTable
                .SelectMany(x => x.Value)
                .OfType<SourceFunctionSymbol>()
                .FirstOrDefault(x => SyntaxFacts.HaveMatchingSignatures(
                    x.DefinitionSyntax as FunctionSyntax ?? x.DeclarationSyntaxes[0],
                    declaration));

            if (functionSymbol != null)
            {
                if (functionSymbol.DefinitionSyntax != null)
                    Diagnostics.ReportSymbolRedefined(declaration.Name.GetTextSpanSafe(), functionSymbol);
                else
                    functionSymbol.DefinitionSyntax = declaration;
            }
            else
            {
                if (isQualifiedName)
                    Diagnostics.ReportUndeclaredFunctionInNamespaceOrClass((QualifiedDeclarationNameSyntax) declaration.Name);
                functionSymbol = new SourceFunctionSymbol(declaration, parent, boundReturnType.TypeSymbol);
                containerBinder.AddSymbol(functionSymbol, declaration.Name.GetTextSpanSafe(), true);
            }

            if (declaration.Semantic != null)
                Bind(declaration.Semantic, BindVariableQualifier);

            var functionBinder = (functionOwner != null && functionOwner.Kind == SymbolKind.Class)
                ? new ClassMethodBinder(_sharedBinderState, this, (ClassSymbol) functionOwner)
                : new Binder(_sharedBinderState, this);

            if (isQualifiedName)
                functionBinder = new ContainedFunctionBinder(_sharedBinderState, functionBinder, containerSymbol.Binder);

            var boundParameters = BindParameters(declaration.ParameterList, functionBinder, functionSymbol);
            var boundBody = functionBinder.Bind(declaration.Body, x => functionBinder.BindBlock(x, functionSymbol));

            return new BoundFunctionDefinition(functionSymbol, boundReturnType, boundParameters.ToImmutableArray(), boundBody);
        }
        private BoundNode BindFunctionDefinition(FunctionDefinitionSyntax declaration, Symbol parent)
        {
            BindAttributes(declaration.Attributes);

            var boundReturnType = Bind(declaration.ReturnType, x => BindType(x, parent));

            var isQualifiedName = false;

            ContainerSymbol containerSymbol;
            Symbol          functionOwner;

            switch (declaration.Name.Kind)
            {
            case SyntaxKind.IdentifierDeclarationName:
                containerSymbol = null;
                functionOwner   = parent;
                break;

            case SyntaxKind.QualifiedDeclarationName:
                containerSymbol = LookupContainer(((QualifiedDeclarationNameSyntax)declaration.Name).Left);
                if (containerSymbol == null)
                {
                    return(new BoundErrorNode());
                }
                isQualifiedName = true;
                functionOwner   = containerSymbol;
                break;

            default:
                throw new InvalidOperationException();
            }

            var containerBinder = containerSymbol?.Binder ?? this;

            var symbolTable = containerBinder.LocalSymbols;

            var functionSymbol = symbolTable
                                 .SelectMany(x => x.Value)
                                 .OfType <SourceFunctionSymbol>()
                                 .FirstOrDefault(x => SyntaxFacts.HaveMatchingSignatures(
                                                     x.DefinitionSyntax as FunctionSyntax ?? x.DeclarationSyntaxes[0],
                                                     declaration));

            if (functionSymbol != null)
            {
                if (functionSymbol.DefinitionSyntax != null)
                {
                    Diagnostics.ReportSymbolRedefined(declaration.Name.SourceRange, functionSymbol);
                }
                else
                {
                    functionSymbol.DefinitionSyntax = declaration;
                }
            }
            else
            {
                if (isQualifiedName)
                {
                    Diagnostics.ReportUndeclaredFunctionInNamespaceOrClass((QualifiedDeclarationNameSyntax)declaration.Name);
                }
                functionSymbol = new SourceFunctionSymbol(declaration, parent, boundReturnType.TypeSymbol);
                containerBinder.AddSymbol(functionSymbol, declaration.Name.SourceRange, true);
            }

            if (declaration.Semantic != null)
            {
                Bind(declaration.Semantic, BindVariableQualifier);
            }

            var functionBinder = (functionOwner != null && functionOwner.Kind == SymbolKind.Class)
                ? new ClassMethodBinder(_sharedBinderState, this, (ClassSymbol)functionOwner)
                : new Binder(_sharedBinderState, this);

            if (isQualifiedName)
            {
                functionBinder = new ContainedFunctionBinder(_sharedBinderState, functionBinder, containerSymbol.Binder);
            }

            var boundParameters = BindParameters(declaration.ParameterList, functionBinder, functionSymbol);
            var boundBody       = functionBinder.Bind(declaration.Body, x => functionBinder.BindBlock(x, functionSymbol));

            return(new BoundFunctionDefinition(functionSymbol, boundReturnType, boundParameters.ToImmutableArray(), boundBody));
        }