private BoundFunctionDeclaration BindFunctionDeclaration(FunctionDeclarationSyntax declaration, Symbol parent)
        {
            BindAttributes(declaration.Attributes);

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

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

            if (functionSymbol != null)
            {
                functionSymbol.DeclarationSyntaxes.Add(declaration);
            }
            else
            {
                functionSymbol = new SourceFunctionSymbol(declaration, parent, boundReturnType.TypeSymbol);
                AddSymbol(functionSymbol, declaration.Name.SourceRange, true);
            }

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

            var functionBinder = new FunctionBinder(_sharedBinderState, this, functionSymbol);

            var boundParameters = BindParameters(declaration.ParameterList, functionBinder, functionSymbol);

            return(new BoundFunctionDeclaration(functionSymbol, boundReturnType, boundParameters.ToImmutableArray()));
        }
        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 || functionOwner.Kind == SymbolKind.Struct))
                ? new StructMethodBinder(_sharedBinderState, this, (StructSymbol)functionOwner, functionSymbol)
                : new FunctionBinder(_sharedBinderState, this, functionSymbol);

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

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

            if (boundReturnType.Type != IntrinsicTypes.Void && !ContainsReturnStatement(boundBody))
            {
                Diagnostics.Report(declaration.Name.SourceRange, DiagnosticId.ReturnExpected, functionSymbol.Name);
            }

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