public BoundFunctionInvocationExpression(FunctionInvocationExpressionSyntax syntax, ImmutableArray <BoundExpression> arguments, OverloadResolutionResult <FunctionSymbolSignature> result)
     : base(BoundNodeKind.FunctionInvocationExpression)
 {
     Syntax    = syntax;
     Arguments = arguments;
     Result    = result;
 }
 public BoundFunctionInvocationExpression(FunctionInvocationExpressionSyntax syntax, ImmutableArray<BoundExpression> arguments, OverloadResolutionResult<FunctionSymbolSignature> result)
     : base(BoundNodeKind.FunctionInvocationExpression)
 {
     Syntax = syntax;
     Arguments = arguments;
     Result = result;
 }
예제 #3
0
        private ExpressionSyntax ParseDirectiveTerm()
        {
            ExpressionSyntax expr;

            var tk = Current.Kind;

            switch (tk)
            {
            case SyntaxKind.IdentifierToken:
                expr = ParseIdentifier();
                break;

            case SyntaxKind.FalseKeyword:
            case SyntaxKind.TrueKeyword:
            case SyntaxKind.IntegerLiteralToken:
            case SyntaxKind.FloatLiteralToken:
                expr = new LiteralExpressionSyntax(SyntaxFacts.GetLiteralExpression(Current.Kind), NextToken());
                break;

            case SyntaxKind.OpenParenToken:
                expr = ParseDirectiveParenthesizedExpression();
                break;

            default:
                expr = CreateMissingIdentifierName();

                if (tk == SyntaxKind.EndOfFileToken)
                {
                    expr = WithDiagnostic(expr, DiagnosticId.ExpressionExpected);
                }
                else
                {
                    expr = WithDiagnostic(expr, DiagnosticId.InvalidExprTerm, tk.GetText());
                }

                break;
            }

            // Might be function invocation. We only have one function in the preprocessor - "defined".
            if (Current.Kind == SyntaxKind.OpenParenToken && expr.Kind == SyntaxKind.IdentifierName &&
                ((IdentifierNameSyntax)expr).Name.ContextualKind == SyntaxKind.DefinedKeyword)
            {
                _lexer.ExpandMacros = false;

                var openParen = Match(SyntaxKind.OpenParenToken);
                var name      = new IdentifierNameSyntax(NextToken());

                _lexer.ExpandMacros = true;

                var closeParen = Match(SyntaxKind.CloseParenToken);
                expr = new FunctionInvocationExpressionSyntax((IdentifierNameSyntax)expr, new ArgumentListSyntax(
                                                                  openParen,
                                                                  new SeparatedSyntaxList <ExpressionSyntax>(new List <SyntaxNodeBase> {
                    name
                }),
                                                                  closeParen));
            }

            return(expr);
        }
예제 #4
0
        private BoundExpression BindFunctionInvocationExpression(FunctionInvocationExpressionSyntax syntax)
        {
            // Don't try to bind CompileShader function calls, for now.
            if ((syntax.Name.Kind == SyntaxKind.IdentifierName) && ((IdentifierNameSyntax)syntax.Name).Name.ContextualKind == SyntaxKind.CompileShaderKeyword)
            {
                return(new BoundFunctionInvocationExpression(syntax,
                                                             syntax.ArgumentList.Arguments.Select(x => (BoundExpression) new BoundErrorExpression()).ToImmutableArray(),
                                                             OverloadResolutionResult <FunctionSymbolSignature> .None));
            }

            var name           = syntax.Name;
            var boundArguments = BindArgumentList(syntax.ArgumentList);
            var argumentTypes  = boundArguments.Select(a => a.Type).ToImmutableArray();

            var anyErrorsInArguments = argumentTypes.Any(a => a.IsError());

            if (anyErrorsInArguments)
            {
                return(new BoundFunctionInvocationExpression(syntax, boundArguments, OverloadResolutionResult <FunctionSymbolSignature> .None));
            }

            ContainerSymbol containerSymbol;
            SyntaxToken     actualName;

            switch (name.Kind)
            {
            case SyntaxKind.IdentifierName:
                containerSymbol = null;
                actualName      = ((IdentifierNameSyntax)name).Name;
                break;

            case SyntaxKind.QualifiedName:
                containerSymbol = LookupContainer(((QualifiedNameSyntax)syntax.Name).Left);
                actualName      = ((QualifiedNameSyntax)name).Right.Name;
                break;

            default:
                throw new InvalidOperationException();
            }

            var result = (containerSymbol?.Binder ?? this).LookupFunction(actualName, argumentTypes);

            if (result.Best == null)
            {
                if (result.Selected == null)
                {
                    Diagnostics.ReportUndeclaredFunction(syntax, argumentTypes);
                    return(new BoundErrorExpression());
                }

                var symbol1 = result.Selected.Signature.Symbol;
                var symbol2 = result.Candidates.First(c => !c.Signature.Symbol.Equals(symbol1)).Signature.Symbol;
                Diagnostics.ReportAmbiguousInvocation(syntax.GetTextSpanSafe(), symbol1, symbol2, argumentTypes);
            }

            var convertedArguments = boundArguments.Select((a, i) => BindArgument(a, result, i, syntax.ArgumentList.Arguments[i].GetTextSpanSafe())).ToImmutableArray();

            return(new BoundFunctionInvocationExpression(syntax, convertedArguments, result));
        }
예제 #5
0
        private BoundExpression BindAggregateInvocationExpression(FunctionInvocationExpressionSyntax node, AggregateSymbol aggregate)
        {
            var argument          = node.ArgumentList.Arguments[0];
            var argumentBinder    = CreateAggregateArgumentBinder();
            var boundArgument     = argumentBinder.BindExpression(argument);
            var boundAggregatable = BindAggregatable(node.Span, aggregate, boundArgument);
            var boundAggregate    = new BoundAggregateExpression(aggregate, boundAggregatable, boundArgument);

            return(BindAggregate(node, boundAggregate));
        }
예제 #6
0
        public override void VisitFunctionInvocationExpression(FunctionInvocationExpressionSyntax node)
        {
            var symbol = _semanticModel.GetSymbol(node);

            if (symbol != null)
            {
                CreateTag(node.Name.GetUnqualifiedName().Name, HlslClassificationTypeNames.FunctionIdentifier);
            }

            base.VisitFunctionInvocationExpression(node);
        }
예제 #7
0
        private ExpressionSyntax ParseSubExpression(uint precedence)
        {
            if (Current.Kind == SyntaxKind.CompileKeyword)
            {
                var compile = Match(SyntaxKind.CompileKeyword);
                var shaderTarget = Match(SyntaxKind.IdentifierToken);
                var shaderFunctionName = ParseIdentifier();
                var shaderFunction = new FunctionInvocationExpressionSyntax(shaderFunctionName, ParseParenthesizedArgumentList(false));
                return new CompileExpressionSyntax(compile, shaderTarget, shaderFunction);
            }

            ExpressionSyntax leftOperand;
            SyntaxKind opKind;

            // No left operand, so we need to parse one -- possibly preceded by a
            // unary operator.
            var tk = Current.Kind;
            if (SyntaxFacts.IsPrefixUnaryExpression(tk))
            {
                opKind = SyntaxFacts.GetPrefixUnaryExpression(tk);
                leftOperand = ParsePrefixUnaryExpression(opKind);
            }
            else
            {
                // Not a unary operator - get a primary expression.
                leftOperand = ParseTerm();
            }

            while (true)
            {
                // We either have a binary or assignment or compound operator here, or we're finished.
                tk = Current.Kind;

                ExpressionOperatorType operatorType;
                if (SyntaxFacts.IsBinaryExpression(tk) 
                    && (!_greaterThanTokenIsNotOperator || tk != SyntaxKind.GreaterThanToken)
                    && (tk != SyntaxKind.GreaterThanToken || !_allowGreaterThanTokenAroundRhsExpression || Lookahead.Kind != SyntaxKind.SemiToken))
                {
                    operatorType = ExpressionOperatorType.BinaryExpression;
                    opKind = SyntaxFacts.GetBinaryExpression(tk);
                }
                else if (SyntaxFacts.IsAssignmentExpression(tk))
                {
                    operatorType = ExpressionOperatorType.AssignmentExpression;
                    opKind = SyntaxFacts.GetAssignmentExpression(tk);
                }
                else if (tk == SyntaxKind.CommaToken && CommaIsSeparatorStack.Peek() == false)
                {
                    operatorType = ExpressionOperatorType.CompoundExpression;
                    opKind = SyntaxKind.CompoundExpression;
                }
                else
                {
                    break;
                }

                var newPrecedence = SyntaxFacts.GetOperatorPrecedence(opKind);

                Debug.Assert(newPrecedence > 0); // All binary operators must have precedence > 0!

                // Check the precedence to see if we should "take" this operator
                if (newPrecedence < precedence)
                    break;

                // Same precedence, but not right-associative -- deal with this "later"
                if (newPrecedence == precedence && !SyntaxFacts.IsRightAssociative(opKind))
                    break;

                // Precedence is okay, so we'll "take" this operator.
                var opToken = NextToken();

                SyntaxToken lessThanToken = null;
                if (operatorType == ExpressionOperatorType.AssignmentExpression && _allowGreaterThanTokenAroundRhsExpression)
                    lessThanToken = NextTokenIf(SyntaxKind.LessThanToken);

                var rightOperand = ParseSubExpression(newPrecedence);

                SyntaxToken greaterThanToken = null;
                if (lessThanToken != null)
                    greaterThanToken = NextTokenIf(SyntaxKind.GreaterThanToken);

                switch (operatorType)
                {
                    case ExpressionOperatorType.BinaryExpression:
                        leftOperand = new BinaryExpressionSyntax(opKind, leftOperand, opToken, rightOperand);
                        break;
                    case ExpressionOperatorType.AssignmentExpression:
                        leftOperand = new AssignmentExpressionSyntax(opKind, leftOperand, opToken, lessThanToken, rightOperand, greaterThanToken);
                        break;
                    case ExpressionOperatorType.CompoundExpression:
                        leftOperand = new CompoundExpressionSyntax(opKind, leftOperand, opToken, rightOperand);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }

            var conditionalPrecedence = SyntaxFacts.GetOperatorPrecedence(SyntaxKind.ConditionalExpression);
            if (tk == SyntaxKind.QuestionToken && precedence <= conditionalPrecedence)
            {
                var questionToken = NextToken();

                var colonLeft = ParseSubExpression(conditionalPrecedence);
                var colon = Match(SyntaxKind.ColonToken);

                var colonRight = ParseSubExpression(conditionalPrecedence);
                leftOperand = new ConditionalExpressionSyntax(leftOperand, questionToken, colonLeft, colon, colonRight);
            }

            return leftOperand;
        }
 public CompileExpressionSyntax(SyntaxToken compileKeyword, SyntaxToken shaderTargetToken, FunctionInvocationExpressionSyntax shaderFunction)
     : base(SyntaxKind.CompileExpression)
 {
     RegisterChildNode(out CompileKeyword, compileKeyword);
     RegisterChildNode(out ShaderTargetToken, shaderTargetToken);
     RegisterChildNode(out ShaderFunction, shaderFunction);
 }
        private ExpressionSyntax ParseSubExpression(uint precedence)
        {
            if (Current.Kind == SyntaxKind.CompileKeyword)
            {
                var compile            = Match(SyntaxKind.CompileKeyword);
                var shaderTarget       = Match(SyntaxKind.IdentifierToken);
                var shaderFunctionName = ParseIdentifier();
                var shaderFunction     = new FunctionInvocationExpressionSyntax(shaderFunctionName, ParseParenthesizedArgumentList(false));
                return(new CompileExpressionSyntax(compile, shaderTarget, shaderFunction));
            }

            ExpressionSyntax leftOperand;
            SyntaxKind       opKind;

            // No left operand, so we need to parse one -- possibly preceded by a
            // unary operator.
            var tk = Current.Kind;

            if (SyntaxFacts.IsPrefixUnaryExpression(tk))
            {
                opKind      = SyntaxFacts.GetPrefixUnaryExpression(tk);
                leftOperand = ParsePrefixUnaryExpression(opKind);
            }
            else
            {
                // Not a unary operator - get a primary expression.
                leftOperand = ParseTerm();
            }

            while (true)
            {
                // We either have a binary or assignment or compound operator here, or we're finished.
                tk = Current.Kind;

                ExpressionOperatorType operatorType;
                if (SyntaxFacts.IsBinaryExpression(tk) &&
                    (!_greaterThanTokenIsNotOperator || tk != SyntaxKind.GreaterThanToken) &&
                    (tk != SyntaxKind.GreaterThanToken || !_allowGreaterThanTokenAroundRhsExpression || Lookahead.Kind != SyntaxKind.SemiToken))
                {
                    operatorType = ExpressionOperatorType.BinaryExpression;
                    opKind       = SyntaxFacts.GetBinaryExpression(tk);
                }
                else if (SyntaxFacts.IsAssignmentExpression(tk))
                {
                    operatorType = ExpressionOperatorType.AssignmentExpression;
                    opKind       = SyntaxFacts.GetAssignmentExpression(tk);
                }
                else if (tk == SyntaxKind.CommaToken && CommaIsSeparatorStack.Peek() == false)
                {
                    operatorType = ExpressionOperatorType.CompoundExpression;
                    opKind       = SyntaxKind.CompoundExpression;
                }
                else
                {
                    break;
                }

                var newPrecedence = SyntaxFacts.GetOperatorPrecedence(opKind);

                Debug.Assert(newPrecedence > 0); // All binary operators must have precedence > 0!

                // Check the precedence to see if we should "take" this operator
                if (newPrecedence < precedence)
                {
                    break;
                }

                // Same precedence, but not right-associative -- deal with this "later"
                if (newPrecedence == precedence && !SyntaxFacts.IsRightAssociative(opKind))
                {
                    break;
                }

                // Precedence is okay, so we'll "take" this operator.
                var opToken = NextToken();

                SyntaxToken lessThanToken = null;
                if (operatorType == ExpressionOperatorType.AssignmentExpression && _allowGreaterThanTokenAroundRhsExpression)
                {
                    lessThanToken = NextTokenIf(SyntaxKind.LessThanToken);
                }

                var rightOperand = ParseSubExpression(newPrecedence);

                SyntaxToken greaterThanToken = null;
                if (lessThanToken != null)
                {
                    greaterThanToken = NextTokenIf(SyntaxKind.GreaterThanToken);
                }

                switch (operatorType)
                {
                case ExpressionOperatorType.BinaryExpression:
                    leftOperand = new BinaryExpressionSyntax(opKind, leftOperand, opToken, rightOperand);
                    break;

                case ExpressionOperatorType.AssignmentExpression:
                    leftOperand = new AssignmentExpressionSyntax(opKind, leftOperand, opToken, lessThanToken, rightOperand, greaterThanToken);
                    break;

                case ExpressionOperatorType.CompoundExpression:
                    leftOperand = new CompoundExpressionSyntax(opKind, leftOperand, opToken, rightOperand);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var conditionalPrecedence = SyntaxFacts.GetOperatorPrecedence(SyntaxKind.ConditionalExpression);

            if (tk == SyntaxKind.QuestionToken && precedence <= conditionalPrecedence)
            {
                var questionToken = NextToken();

                var colonLeft = ParseSubExpression(conditionalPrecedence);
                var colon     = Match(SyntaxKind.ColonToken);

                var colonRight = ParseSubExpression(conditionalPrecedence);
                leftOperand = new ConditionalExpressionSyntax(leftOperand, questionToken, colonLeft, colon, colonRight);
            }

            return(leftOperand);
        }
 public static void ReportFunctionMissingImplementation(this ICollection <Diagnostic> diagnostics, FunctionInvocationExpressionSyntax syntax)
 {
     diagnostics.Report(syntax.Name.SourceRange, DiagnosticId.FunctionMissingImplementation, syntax.Name.ToStringIgnoringMacroReferences());
 }
        public static void ReportOverloadResolutionFailure(this ICollection <Diagnostic> diagnostics, FunctionInvocationExpressionSyntax node, int argumentCount)
        {
            var name = node.Name.ToStringIgnoringMacroReferences();

            diagnostics.Report(node.SourceRange, DiagnosticId.FunctionOverloadResolutionFailure, name, argumentCount);
        }
        public static void ReportUndeclaredFunction(this ICollection <Diagnostic> diagnostics, FunctionInvocationExpressionSyntax node, IEnumerable <TypeSymbol> argumentTypes)
        {
            var name             = node.Name.ToStringIgnoringMacroReferences();
            var argumentTypeList = string.Join(@", ", argumentTypes.Select(t => t.ToDisplayName()));

            diagnostics.Report(node.SourceRange, DiagnosticId.UndeclaredFunction, name, argumentTypeList);
        }
예제 #13
0
        private ExpressionSyntax ParseDirectiveTerm()
        {
            ExpressionSyntax expr;

            var tk = Current.Kind;
            switch (tk)
            {
                case SyntaxKind.IdentifierToken:
                    expr = ParseIdentifier();
                    break;
                case SyntaxKind.FalseKeyword:
                case SyntaxKind.TrueKeyword:
                case SyntaxKind.IntegerLiteralToken:
                case SyntaxKind.FloatLiteralToken:
                    expr = new LiteralExpressionSyntax(SyntaxFacts.GetLiteralExpression(Current.Kind), NextToken());
                    break;
                case SyntaxKind.OpenParenToken:
                    expr = ParseDirectiveParenthesizedExpression();
                    break;
                default:
                    expr = CreateMissingIdentifierName();

                    if (tk == SyntaxKind.EndOfFileToken)
                        expr = WithDiagnostic(expr, DiagnosticId.ExpressionExpected);
                    else
                        expr = WithDiagnostic(expr, DiagnosticId.InvalidExprTerm, tk.GetText());

                    break;
            }

            // Might be function invocation. We only have one function in the preprocessor - "defined".
            if (Current.Kind == SyntaxKind.OpenParenToken && expr.Kind == SyntaxKind.IdentifierName
                && ((IdentifierNameSyntax) expr).Name.ContextualKind == SyntaxKind.DefinedKeyword)
            {
                _lexer.ExpandMacros = false;

                var openParen = Match(SyntaxKind.OpenParenToken);
                var name = new IdentifierNameSyntax(NextToken());

                _lexer.ExpandMacros = true;

                var closeParen = Match(SyntaxKind.CloseParenToken);
                expr = new FunctionInvocationExpressionSyntax((IdentifierNameSyntax) expr, new ArgumentListSyntax(
                    openParen,
                    new SeparatedSyntaxList<ExpressionSyntax>(new List<SyntaxNode> { name }),
                    closeParen));
            }

            return expr;
        }
예제 #14
0
 public virtual void VisitFunctionInvocationExpression(FunctionInvocationExpressionSyntax node)
 {
     DefaultVisit(node);
 }
예제 #15
0
 public static void ReportUndeclaredFunction(this ICollection<Diagnostic> diagnostics, FunctionInvocationExpressionSyntax node, IEnumerable<TypeSymbol> argumentTypes)
 {
     var name = node.Name.ToStringIgnoringMacroReferences();
     var argumentTypeList = string.Join(@", ", argumentTypes.Select(t => t.ToDisplayName()));
     diagnostics.Report(node.GetTextSpanSafe(), DiagnosticId.UndeclaredFunction, name, argumentTypeList);
 }
예제 #16
0
 public virtual void VisitFunctionInvocationExpression(FunctionInvocationExpressionSyntax node)
 {
     DefaultVisit(node);
 }
예제 #17
0
        public override void VisitFunctionInvocationExpression(FunctionInvocationExpressionSyntax node)
        {
            var symbol = _semanticModel.GetSymbol(node);
            if (symbol != null)
                CreateTag(node.Name.GetUnqualifiedName().Name, _classificationService.FunctionIdentifier);

            base.VisitFunctionInvocationExpression(node);
        }
예제 #18
0
        public static void ReportUndeclaredFunction(this ICollection <Diagnostic> diagnostics, FunctionInvocationExpressionSyntax node, IEnumerable <Type> argumentTypes)
        {
            var name             = node.Name.ValueText;
            var argumentTypeList = string.Join(@", ", argumentTypes.Select(t => t.ToDisplayName()));

            diagnostics.Report(node.Span, DiagnosticId.UndeclaredFunction, name, argumentTypeList);
        }
예제 #19
0
        private BoundExpression BindFunctionInvocationExpression(FunctionInvocationExpressionSyntax node)
        {
            if (node.ArgumentList.Arguments.Count == 1)
            {
                // Could be an aggregate or a function.

                var aggregates       = LookupAggregate(node.Name).ToImmutableArray();
                var funcionCandidate = LookupFunctionWithSingleParameter(node.Name).FirstOrDefault();

                if (aggregates.Length > 0)
                {
                    if (funcionCandidate != null)
                    {
                        var symbols = new Symbol[] { aggregates[0], funcionCandidate };
                        Diagnostics.ReportAmbiguousName(node.Name, symbols);
                    }
                    else
                    {
                        if (aggregates.Length > 1)
                        {
                            Diagnostics.ReportAmbiguousAggregate(node.Name, aggregates);
                        }

                        var aggregate = aggregates[0];
                        return(BindAggregateInvocationExpression(node, aggregate));
                    }
                }
            }

            var name          = node.Name;
            var arguments     = node.ArgumentList.Arguments.Select(BindExpression).ToImmutableArray();
            var argumentTypes = arguments.Select(a => a.Type).ToImmutableArray();

            // To avoid cascading errors, we'll return a node that isn't bound to any function
            // if we couldn't resolve any of our arguments.

            var anyErrorsInArguments = argumentTypes.Any(a => a.IsError());

            if (anyErrorsInArguments)
            {
                return(new BoundFunctionInvocationExpression(arguments, OverloadResolutionResult <FunctionSymbolSignature> .None));
            }

            var result = LookupFunction(name, argumentTypes);

            if (result.Best == null)
            {
                if (result.Selected == null)
                {
                    Diagnostics.ReportUndeclaredFunction(node, argumentTypes);
                    return(new BoundErrorExpression());
                }

                var symbol1 = result.Selected.Signature.Symbol;
                var symbol2 = result.Candidates.First(c => c.IsSuitable && c.Signature.Symbol != symbol1).Signature.Symbol;
                Diagnostics.ReportAmbiguousInvocation(node.Span, symbol1, symbol2, argumentTypes);
            }

            // Convert all arguments (if necessary)

            var convertedArguments = arguments.Select((a, i) => BindArgument(a, result, i)).ToImmutableArray();

            return(new BoundFunctionInvocationExpression(convertedArguments, result));
        }
예제 #20
0
 public virtual TResult VisitFunctionInvocationExpression(FunctionInvocationExpressionSyntax node)
 {
     return(DefaultVisit(node));
 }
예제 #21
0
 public static void ReportFunctionMissingImplementation(this ICollection<Diagnostic> diagnostics, FunctionInvocationExpressionSyntax syntax)
 {
     diagnostics.Report(syntax.Name.GetTextSpanSafe(), DiagnosticId.FunctionMissingImplementation, syntax.Name.ToStringIgnoringMacroReferences());
 }
 private void ClassifyFunctionInvocationExpression(FunctionInvocationExpressionSyntax node)
 {
     ClassifyExpression(node, node.Name);
     ClassifyNode(node.ArgumentList);
 }