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); }