Exemple #1
0
        private DataType InferInvocationType(InvocationSyntax invocation)
        {
            // This could:
            // * Invoke a stand alone function
            // * Invoke a static function
            // * Invoke a method
            // * Invoke a function pointer
            var argumentTypes = invocation.Arguments.Select(InferArgumentType).ToFixedList();

            InferExpressionTypeInInvocation(invocation.Callee, argumentTypes);
            var callee = invocation.Callee.Type;

            if (callee is FunctionType functionType)
            {
                foreach (var(arg, type) in invocation.Arguments.Zip(functionType.ParameterTypes))
                {
                    InsertImplicitConversionIfNeeded(ref arg.Value, type);
                    CheckArgumentTypeCompatibility(type, arg);
                }

                return(invocation.Type = functionType.ReturnType);
            }

            // If it is unknown, we already reported an error
            if (callee == DataType.Unknown)
            {
                return(invocation.Type = DataType.Unknown);
            }

            diagnostics.Add(TypeError.MustBeCallable(file, invocation.Callee));
            return(invocation.Type = DataType.Unknown);
        }
 public virtual void VisitInvocation(InvocationSyntax invocation, A args)
 {
     VisitExpression(invocation.Callee, args);
     foreach (var argument in invocation.Arguments)
     {
         VisitArgument(argument, args);
     }
 }
        public override void VisitInvocation(InvocationSyntax invocation, Void args)
        {
            base.VisitInvocation(invocation, args);

            CheckArguments(invocation.Callee.Type, invocation.Arguments);

            // Functions returning ownership are effectively move
            if (invocation.Type is ReferenceType returnType && returnType.IsOwned)
            {
                invocation.ValueSemantics = ValueSemantics.Move;
            }
        }
        private Value ConvertInvocationToValue(BlockBuilder currentBlock, InvocationSyntax invocation)
        {
            switch (invocation.Callee)
            {
            case IdentifierNameSyntax identifier:
            {
                var symbol    = identifier.ReferencedSymbol;
                var arguments = invocation.Arguments
                                .Select(a => ConvertToOperand(currentBlock, a.Value)).ToList();
                return(new FunctionCall(symbol.FullName, arguments, invocation.Span));
            }

            case MemberAccessExpressionSyntax memberAccess:
            {
                var self      = ConvertToOperand(currentBlock, memberAccess.Expression);
                var arguments = invocation.Arguments
                                .Select(a => ConvertToOperand(currentBlock, a.Value)).ToList();
                var symbol = memberAccess.ReferencedSymbol;
                switch (symbol)
                {
                case IFunctionSymbol function:
                    switch (memberAccess.Expression.Type)
                    {
                    case SimpleType _:
                        // case StructType _:
                        // Full name because this isn't a member
                        return(new FunctionCall(function.FullName, self, arguments, invocation.Span));

                    default:
                        return(new VirtualFunctionCall(invocation.Span, function.FullName.UnqualifiedName, self, arguments));
                    }

                default:
                    throw NonExhaustiveMatchException.For(symbol);
                }
            }

            default:
                throw NonExhaustiveMatchException.For(invocation.Callee);
            }
        }
        /// <summary>
        /// For expressions, we switch to a precedence climbing parser.
        /// </summary>
        public ExpressionSyntax ParseExpression(OperatorPrecedence minPrecedence)
        {
            var expression = ParseAtom();

            for (; ;)
            {
                IOperatorToken     @operator  = null;
                OperatorPrecedence?precedence = null;
                var leftAssociative           = true;
                switch (Tokens.Current)
                {
                case IEqualsToken _:
                case IPlusEqualsToken _:
                case IMinusEqualsToken _:
                case IAsteriskEqualsToken _:
                case ISlashEqualsToken _:
                    if (minPrecedence <= OperatorPrecedence.Assignment)
                    {
                        precedence      = OperatorPrecedence.Assignment;
                        leftAssociative = false;
                        @operator       = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IQuestionQuestionToken _:
                    if (minPrecedence <= OperatorPrecedence.Coalesce)
                    {
                        precedence = OperatorPrecedence.Coalesce;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IOrKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.LogicalOr)
                    {
                        precedence = OperatorPrecedence.LogicalOr;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IAndKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.LogicalAnd)
                    {
                        precedence = OperatorPrecedence.LogicalAnd;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IEqualsEqualsToken _:
                case INotEqualToken _:
                    if (minPrecedence <= OperatorPrecedence.Equality)
                    {
                        precedence = OperatorPrecedence.Equality;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case ILessThanToken _:
                case ILessThanOrEqualToken _:
                case IGreaterThanToken _:
                case IGreaterThanOrEqualToken _:
                case ILessThanColonToken _:     // Subtype operator
                case IAsKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.Relational)
                    {
                        precedence = OperatorPrecedence.Relational;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IColonToken _:     // type kind
                    if (minPrecedence <= OperatorPrecedence.Relational)
                    {
                        var      colon = Tokens.Expect <IColonToken>();
                        TypeKind typeKind;
                        switch (Tokens.Current)
                        {
                        case IClassKeywordToken _:
                            typeKind = TypeKind.Class;
                            break;

                        case IStructKeywordToken _:
                            typeKind = TypeKind.Struct;
                            break;

                        default:
                            Tokens.Expect <ITypeKindKeywordToken>();
                            // We saw a colon without what we expected after, just assume it is missing
                            continue;
                        }
                        var typeKindSpan = Tokens.Expect <ITypeKindKeywordToken>();
                        var span         = TextSpan.Covering(colon, typeKindSpan);
                        expression = new TypeKindExpressionSyntax(span, typeKind);
                        continue;
                    }
                    break;

                case IDotDotToken _:
                case ILessThanDotDotToken _:
                case IDotDotLessThanToken _:
                case ILessThanDotDotLessThanToken _:
                    if (minPrecedence <= OperatorPrecedence.Range)
                    {
                        precedence = OperatorPrecedence.Range;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IPlusToken _:
                case IMinusToken _:
                    if (minPrecedence <= OperatorPrecedence.Additive)
                    {
                        precedence = OperatorPrecedence.Additive;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IAsteriskToken _:
                case ISlashToken _:
                    if (minPrecedence <= OperatorPrecedence.Multiplicative)
                    {
                        precedence = OperatorPrecedence.Multiplicative;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IDollarToken _:
                    if (minPrecedence <= OperatorPrecedence.Lifetime)
                    {
                        Tokens.Expect <IDollarToken>();
                        var(nameSpan, lifetime) = ParseLifetimeName();
                        expression = new ReferenceLifetimeSyntax(expression, nameSpan, lifetime);
                        continue;
                    }
                    break;

                case IQuestionToken _:
                    if (minPrecedence <= OperatorPrecedence.Unary)
                    {
                        var question = Tokens.Required <IQuestionToken>();
                        var span     = TextSpan.Covering(expression.Span, question);
                        expression = new UnaryExpressionSyntax(span, UnaryOperatorFixity.Postfix, UnaryOperator.Question, expression);
                        continue;
                    }
                    break;

                case IOpenParenToken _:
                    if (minPrecedence <= OperatorPrecedence.Primary)
                    {
                        var callee = expression;
                        Tokens.Expect <IOpenParenToken>();
                        var arguments      = ParseArguments();
                        var closeParenSpan = Tokens.Expect <ICloseParenToken>();
                        var span           = TextSpan.Covering(callee.Span, closeParenSpan);
                        expression = new InvocationSyntax(span, callee, arguments);
                        continue;
                    }
                    break;

                case IDotToken _:
                case ICaretDotToken _:
                case IQuestionDotToken _:
                    if (minPrecedence <= OperatorPrecedence.Primary)
                    {
                        // Member Access
                        var accessOperator = BuildAccessOperator(Tokens.RequiredToken <IAccessOperatorToken>());
                        var member         = ParseSimpleName();
                        var span           = TextSpan.Covering(expression.Span, member.Span);
                        expression = new MemberAccessExpressionSyntax(span, expression, accessOperator, member);
                        continue;
                    }
                    break;

                default:
                    return(expression);
                }

                if (@operator is IOperatorToken operatorToken &&
                    precedence is OperatorPrecedence operatorPrecedence)
                {
                    if (leftAssociative)
                    {
                        operatorPrecedence += 1;
                    }

                    var rightOperand = ParseExpression(operatorPrecedence);
                    expression = BuildOperatorExpression(expression, operatorToken, rightOperand);
                }