Exemple #1
0
        private bool BindInWhileStatement(WhileStatementNode whileStatement,
                                          VariableIdentifierMap variableIdentifierMap)
        {
            TypeSymbolNode?conditionType = BindInExpression(whileStatement.ConditionNode, variableIdentifierMap);

            if (conditionType == null)
            {
                return(false);
            }

            TypeSymbolNode?boolType = typeManager[FrameworkType.Bool];

            if (!TypeIsCompatibleWith(conditionType,
                                      boolType,
                                      possiblyOffendingNode: whileStatement.ConditionNode,
                                      out ImplicitConversionSymbolNode? conversion))
            {
                return(false);
            }

            if (conversion != null)
            {
                whileStatement.ConditionNode.SpecifyImplicitConversion(conversion);
            }

            bool success = BindInStatementBlock(whileStatement.StatementNodes, variableIdentifierMap);

            return(success);
        }
        private TypeSymbolNode?BindInUnaryOperation(UnaryOperationExpressionNode unaryOperation,
                                                    VariableIdentifierMap variableIdentifierMap)
        {
            TypeSymbolNode?operandType = BindInExpression(unaryOperation.OperandNode, variableIdentifierMap);

            if (operandType == null)
            {
                return(null);
            }

            Operator @operator = unaryOperation.Operator;

            UnaryOperationSymbolNode?operationSymbol = FindBestUnaryOperation(@operator,
                                                                              operandType,
                                                                              out ImplicitConversionSymbolNode? conversion);

            if (operationSymbol == null)
            {
                ErrorProvider.ReportError(ErrorCode.OperatorNotAvailableForTypes,
                                          Compilation,
                                          unaryOperation,
                                          $"Operand type: {operandType.Identifier}");
                return(null);
            }

            if (conversion != null)
            {
                unaryOperation.OperandNode.SpecifyImplicitConversion(conversion);
            }

            unaryOperation.Bind(operationSymbol);

            return(operationSymbol.ReturnTypeNode);
        }
Exemple #3
0
        private bool BindInIfStatement(IfStatementNode ifStatement, VariableIdentifierMap variableIdentifierMap)
        {
            TypeSymbolNode?ifConditionType = BindInExpression(ifStatement.ConditionNode, variableIdentifierMap);

            if (ifConditionType == null)
            {
                return(false);
            }

            TypeSymbolNode boolType = typeManager[FrameworkType.Bool];

            if (!TypeIsCompatibleWith(ifConditionType,
                                      boolType,
                                      possiblyOffendingNode: ifStatement.ConditionNode,
                                      out ImplicitConversionSymbolNode? conversion))
            {
                return(false);
            }

            if (conversion != null)
            {
                ifStatement.ConditionNode.SpecifyImplicitConversion(conversion);
            }

            bool success = BindInStatementBlock(ifStatement.StatementNodes, variableIdentifierMap);

            if (!success)
            {
                return(false);
            }

            foreach (ElseIfPartNode elseIfPart in ifStatement.ElseIfPartNodes)
            {
                TypeSymbolNode?elseIfConditionType = BindInExpression(elseIfPart.ConditionNode, variableIdentifierMap);

                if (elseIfConditionType == null)
                {
                    return(false);
                }

                success = BindInStatementBlock(elseIfPart.StatementNodes, variableIdentifierMap);

                if (!success)
                {
                    return(false);
                }
            }

            success = true;

            if (ifStatement.ElsePartNode != null)
            {
                success = BindInStatementBlock(ifStatement.ElsePartNode.StatementNodes, variableIdentifierMap);
            }

            return(success);
        }
        private TypeSymbolNode?BindInBinaryOperation(BinaryOperationExpressionNode binaryOperation,
                                                     VariableIdentifierMap variableIdentifierMap)
        {
            TypeSymbolNode?leftType = BindInExpression(binaryOperation.LeftOperandNode, variableIdentifierMap);

            if (leftType == null)
            {
                return(null);
            }

            TypeSymbolNode?rightType = BindInExpression(binaryOperation.RightOperandNode, variableIdentifierMap);

            if (rightType == null)
            {
                return(null);
            }

            Operator @operator = binaryOperation.Operator;

            BinaryOperationSymbolNode?operationSymbol = FindBestBinaryOperation(@operator,
                                                                                leftType,
                                                                                rightType,
                                                                                out ImplicitConversionSymbolNode? implicitConversionLeft,
                                                                                out ImplicitConversionSymbolNode? implicitConversionRight);

            if (implicitConversionLeft != null)
            {
                binaryOperation.LeftOperandNode.SpecifyImplicitConversion(implicitConversionLeft);
            }

            if (implicitConversionRight != null)
            {
                binaryOperation.RightOperandNode.SpecifyImplicitConversion(implicitConversionRight);
            }

            if (operationSymbol == null)
            {
                ErrorProvider.ReportError(ErrorCode.OperatorNotAvailableForTypes,
                                          Compilation,
                                          binaryOperation,
                                          $"Left type: {leftType.Identifier}",
                                          $"Right type: {rightType.Identifier}");
                return(null);
            }

            binaryOperation.Bind(operationSymbol);

            return(operationSymbol.ReturnTypeNode);
        }
Exemple #5
0
        private bool BindInVariableAssignment(VariableAssignmentStatementNode variableAssignment,
                                              VariableIdentifierMap variableIdentifierMap)
        {
            TypeSymbolNode?assignedType = BindInExpression(variableAssignment.AssignedExpressionNode,
                                                           variableIdentifierMap);

            if (assignedType == null)
            {
                return(false);
            }

            if (!variableIdentifierMap.TryGet(variableAssignment.VariableIdentifier,
                                              out VariableSymbolNode? variable))
            {
                ErrorProvider.ReportError(ErrorCode.CantAssignUndeclaredVariable,
                                          Compilation,
                                          variableAssignment,
                                          $"Variable name: {variableAssignment.VariableIdentifier}");
                return(false);
            }

            if (variable.IsReadOnly)
            {
                ErrorProvider.ReportError(ErrorCode.CantReAssignReadOnlyVariable,
                                          Compilation,
                                          variableAssignment);
                return(false);
            }

            if (!TypeIsCompatibleWith(assignedType,
                                      variable.TypeNode,
                                      possiblyOffendingNode: variableAssignment.AssignedExpressionNode,
                                      out ImplicitConversionSymbolNode? conversion))
            {
                return(false);
            }

            variableAssignment.Bind(variable);

            if (conversion != null)
            {
                variableAssignment.AssignedExpressionNode.SpecifyImplicitConversion(conversion);
            }

            return(true);
        }
Exemple #6
0
        private bool BindInStatement(StatementNode statement,
                                     VariableIdentifierMap variableIdentifierMap)
        {
            switch (statement)
            {
            case BlockStatementNode blockStatement:
                return(BindInStatementBlock(blockStatement.StatementNodes, variableIdentifierMap));

            case FunctionCallStatementNode functionCall:
            {
                (_, bool success) = BindInFunctionCall(functionCall.UnderlyingFunctionCallExpressionNode,
                                                       variableIdentifierMap,
                                                       expressionContext: false);
                return(success);
            }

            case ForStatementNode forStatement:
                return(BindInForStatement(forStatement, variableIdentifierMap));

            case IfStatementNode ifStatement:
                return(BindInIfStatement(ifStatement, variableIdentifierMap));

            case LoopControlStatementNode loopControlStatement:
                return(BindInLoopControlStatement(loopControlStatement));

            case ReturnStatementNode returnStatement:
                return(BindInReturnStatement(returnStatement, variableIdentifierMap));

            case VariableAssignmentStatementNode variableAssignment:
                return(BindInVariableAssignment(variableAssignment, variableIdentifierMap));

            case VariableDeclarationStatementNode variableDeclaration:
                return(BindInVariableDeclaration(variableDeclaration, variableIdentifierMap));

            case WhileStatementNode whileStatement:
                return(BindInWhileStatement(whileStatement, variableIdentifierMap));

            default:
                Debug.Fail(message: "A type was forgotten...");
                return(false);
            }
        }
Exemple #7
0
        private bool BindInStatementBlock(StatementCollectionNode statements,
                                          VariableIdentifierMap variableIdentifierMap)
        {
            variableIdentifierMap.EnterBlock();

            foreach (StatementNode statement in statements)
            {
                bool success = BindInStatement(statement,
                                               variableIdentifierMap);

                if (!success)
                {
                    return(false);
                }
            }

            variableIdentifierMap.LeaveBlock();

            return(true);
        }
        private TypeSymbolNode?BindInExpression(ExpressionNode expression,
                                                VariableIdentifierMap variableIdentifierMap)
        {
            switch (expression)
            {
            case BinaryOperationExpressionNode binaryOperation:
                return(BindInBinaryOperation(binaryOperation, variableIdentifierMap));

            case FunctionCallExpressionNode functionCall:
            {
                (TypeSymbolNode? type, bool success) = BindInFunctionCall(functionCall,
                                                                          variableIdentifierMap,
                                                                          expressionContext: true);

                if (!success)
                {
                    return(null);
                }

                Debug.Assert(type != null);
                return(type);
            }

            case IdentifierExpressionNode identifierExpression:
                return(BindIdentifierExpression(identifierExpression, variableIdentifierMap));

            case LiteralExpressionNode literal:
                return(typeManager[literal.AssociatedType]);

            case PropertyGetExpressionNode propertyGet:
                return(BindInPropertyGet(propertyGet, variableIdentifierMap));

            case UnaryOperationExpressionNode unaryOperation:
                return(BindInUnaryOperation(unaryOperation, variableIdentifierMap));

            default:
                Debug.Fail(message: "A type was forgotten...");
                return(null);
            }
        }
        private TypeSymbolNode?BindIdentifierExpression(IdentifierExpressionNode identifierExpression,
                                                        VariableIdentifierMap variableIdentifierMap)
        {
            SymbolNode?symbol = GetExpressionSymbol(identifierExpression.Identifier, variableIdentifierMap);

            if (symbol == null)
            {
                ErrorProvider.ReportError(ErrorCode.CantFindIdentifierInScope,
                                          Compilation,
                                          identifierExpression);
                return(null);
            }

            identifierExpression.Bind(symbol);

            switch (symbol)
            {
            case VariableSymbolNode variable:
            {
                TypeSymbolNode?variableType = variable.TypeNode;
                Debug.Assert(variableType != null);
                return(variableType);
            }

            case ConstantSymbolNode constant:
                return(constant.Type);

            case FunctionSymbolNode:
                ErrorProvider.ReportError(ErrorCode.FunctionNotValidInContext,
                                          Compilation,
                                          identifierExpression);
                return(null);

            default:
                Debug.Fail(message: "A type was forgotten...");
                return(null);
            }
        }
        private TypeSymbolNode?BindInPropertyGet(PropertyGetExpressionNode propertyGet,
                                                 VariableIdentifierMap variableIdentifierMap)
        {
            TypeSymbolNode?expressionType = BindInExpression(propertyGet.ExpressionNode, variableIdentifierMap);

            if (expressionType == null)
            {
                return(null);
            }

            if (!expressionType.PropertyNodes.TryGetValue(propertyGet.PropertyIdentifier, out PropertySymbolNode? property))
            {
                ErrorProvider.ReportError(ErrorCode.PropertyDoesNotExistInType,
                                          Compilation,
                                          propertyGet.PropertyIdentifierNode,
                                          $"Type: {expressionType.Identifier}");
                return(null);
            }

            propertyGet.Bind(property);

            return(property.TypeNode);
        }
Exemple #11
0
        private bool BindInForStatement(ForStatementNode forStatement, VariableIdentifierMap variableIdentifierMap)
        {
            variableIdentifierMap.EnterBlock();

            TypeSymbolNode iterationVariableType;

            if (forStatement.DeclaresNew)
            {
                Debug.Assert(forStatement.InitialValueNode != null);

                TypeSymbolNode?assignedValueType = BindInExpression(forStatement.InitialValueNode, variableIdentifierMap);

                if (assignedValueType == null)
                {
                    return(false);
                }

                iterationVariableType = assignedValueType;

                VariableSymbolNode variable = forStatement.CreateVariable(iterationVariableType);

                variableIdentifierMap.AddSymbol(forStatement.VariableIdentifier, variable);
            }
            else
            {
                SymbolNode?symbol = GetExpressionSymbol(forStatement.VariableIdentifier, variableIdentifierMap);

                if (symbol == null)
                {
                    ErrorProvider.ReportError(ErrorCode.CantFindIdentifierInScope,
                                              Compilation,
                                              forStatement.VariableIdentifierNode);
                    return(false);
                }

                if (symbol is not VariableSymbolNode variable)
                {
                    ErrorProvider.ReportError(ErrorCode.ForNotVariable,
                                              Compilation,
                                              forStatement.VariableIdentifierNode,
                                              $"Identifier: {forStatement.VariableIdentifier}");
                    return(false);
                }

                Debug.Assert(variable.TypeNode != null);
                iterationVariableType = variable.TypeNode;

                if (forStatement.InitialValueNode != null)
                {
                    TypeSymbolNode?assignedValueType = BindInExpression(forStatement.InitialValueNode, variableIdentifierMap);

                    if (assignedValueType == null)
                    {
                        return(false);
                    }

                    if (!TypeIsCompatibleWith(assignedValueType,
                                              iterationVariableType,
                                              possiblyOffendingNode: forStatement.InitialValueNode,
                                              out ImplicitConversionSymbolNode? implicitConversion))
                    {
                        if (implicitConversion != null)
                        {
                            forStatement.InitialValueNode.SpecifyImplicitConversion(implicitConversion);
                        }

                        return(false);
                    }
                }
            }

            {
                TypeSymbolNode?intType      = typeManager[FrameworkType.Int];
                TypeSymbolNode?rationalType = typeManager[FrameworkType.Rational];
                TypeSymbolNode?complexType  = typeManager[FrameworkType.Complex];

                if (iterationVariableType != intType &&
                    iterationVariableType != rationalType &&
                    iterationVariableType != complexType)
                {
                    ErrorProvider.ReportError(ErrorCode.ForIterationVariableHasToBeNumberType,
                                              Compilation,
                                              forStatement.VariableIdentifierNode,
                                              $"Type of iteration variable: {iterationVariableType.Identifier}");
                    return(false);
                }
            }

            if (forStatement.ConditionNode != null)
            {
                TypeSymbolNode?conditionType = BindInExpression(forStatement.ConditionNode, variableIdentifierMap);

                if (conditionType == null)
                {
                    return(false);
                }

                TypeSymbolNode?boolType = typeManager[FrameworkType.Bool];

                if (!TypeIsCompatibleWith(conditionType,
                                          boolType,
                                          possiblyOffendingNode: forStatement.ConditionNode,
                                          out ImplicitConversionSymbolNode? conversion))
                {
                    return(false);
                }

                if (conversion != null)
                {
                    forStatement.ConditionNode.SpecifyImplicitConversion(conversion);
                }
            }

            if (forStatement.WithExpressionNode != null)
            {
                TypeSymbolNode?withType = BindInExpression(forStatement.WithExpressionNode, variableIdentifierMap);

                if (withType == null)
                {
                    return(false);
                }

                if (!TypeIsCompatibleWith(withType,
                                          iterationVariableType,
                                          possiblyOffendingNode: forStatement.WithExpressionNode,
                                          out ImplicitConversionSymbolNode? conversion))
                {
                    return(false);
                }

                if (conversion != null)
                {
                    forStatement.WithExpressionNode.SpecifyImplicitConversion(conversion);
                }
            }

            bool success = BindInStatementBlock(forStatement.StatementNodes, variableIdentifierMap);

            if (!success)
            {
                return(false);
            }

            variableIdentifierMap.LeaveBlock();

            return(true);
        }
Exemple #12
0
        private bool BindInVariableDeclaration(VariableDeclarationStatementNode variableDeclaration,
                                               VariableIdentifierMap variableIdentifierMap)
        {
            if (variableIdentifierMap.TryGet(variableDeclaration.VariableIdentifier, out VariableSymbolNode? _))
            {
                ErrorProvider.ReportError(ErrorCode.CantRedeclareVariable,
                                          Compilation,
                                          variableDeclaration.VariableIdentifierNode);
                return(false);
            }

            VariableSymbolNode variable;

            if (variableDeclaration.AssignedExpressionNode != null)
            {
                TypeSymbolNode?assignedType = BindInExpression(variableDeclaration.AssignedExpressionNode,
                                                               variableIdentifierMap);

                if (assignedType == null)
                {
                    return(false);
                }

                if (variableDeclaration.TypeSpecNode == null)
                {
                    variable = variableDeclaration.CreateVariable(typeSymbol: assignedType);
                }
                else
                {
                    if (!typeManager.TryGetTypeSymbol(variableDeclaration.TypeSpecNode, out TypeSymbolNode? variableType))
                    {
                        return(false);
                    }
                    else if (!TypeIsCompatibleWith(assignedType,
                                                   variableType,
                                                   variableDeclaration.AssignedExpressionNode,
                                                   out ImplicitConversionSymbolNode? conversion))
                    {
                        return(false);
                    }
                    else
                    {
                        if (conversion != null)
                        {
                            variableDeclaration.AssignedExpressionNode.SpecifyImplicitConversion(conversion);
                        }

                        variable = variableDeclaration.CreateVariable(variableType);
                    }
                }
            }
            else
            {
                if (typeManager.TryGetTypeSymbol(variableDeclaration.TypeSpecNode, out TypeSymbolNode? variableType))
                {
                    variable = variableDeclaration.CreateVariable(variableType);
                }
                else
                {
                    return(false);
                }
            }

            variableIdentifierMap.AddSymbol(variableDeclaration.VariableIdentifier, variable);

            return(true);
        }
Exemple #13
0
        private bool BindInReturnStatement(ReturnStatementNode returnStatement, VariableIdentifierMap variableIdentifierMap)
        {
            TypeSymbolNode?returnedType = null;

            if (returnStatement.ReturnExpressionNode != null)
            {
                returnedType = BindInExpression(returnStatement.ReturnExpressionNode, variableIdentifierMap);

                if (returnedType == null)
                {
                    return(false);
                }
            }

            IExecutableNode functionOrProgram = FindReturnableParent(returnStatement);

            if (!typeManager.TryGetTypeSymbol(functionOrProgram.ReturnTypeNode,
                                              out TypeSymbolNode? actualReturnType))
            {
                return(false);
            }

            if (returnedType == null)
            {
                if (actualReturnType != null)
                {
                    string functionName = functionOrProgram is FunctionDeclarationNode declaration
                                        ? declaration.Identifier
                                        : "<Program>";

                    ErrorProvider.ReportError(ErrorCode.ReturnedNoValueEvenThoughFunctionShouldReturn,
                                              Compilation,
                                              (Node?)returnStatement.ReturnExpressionNode ?? returnStatement,
                                              $"Function: {functionName}");
                    return(false);
                }

                return(true);
            }
            else if (actualReturnType == null)
            {
                string functionName = functionOrProgram is FunctionDeclarationNode declaration
                                    ? declaration.Identifier
                                    : "<Program>";

                ErrorProvider.ReportError(ErrorCode.ReturnedValueEvenThoughFunctionDoesNotHaveReturnType,
                                          Compilation,
                                          (Node?)returnStatement.ReturnExpressionNode ?? returnStatement,
                                          $"Function: {functionName}");
                return(false);
            }

            if (!TypeIsCompatibleWith(returnedType,
                                      actualReturnType,
                                      possiblyOffendingNode: returnStatement.ReturnExpressionNode !,
                                      out ImplicitConversionSymbolNode? conversion))
            {
                return(false);
            }

            if (conversion != null)
            {
                returnStatement.ReturnExpressionNode !.SpecifyImplicitConversion(conversion);
            }

            return(true);
        }
        private (TypeSymbolNode?, bool) BindInFunctionCall(FunctionCallExpressionNode functionCall,
                                                           VariableIdentifierMap variableIdentifierMap,
                                                           bool expressionContext)
        {
            if (functionCall.FunctionExpressionNode is not IdentifierExpressionNode identifierExpression)
            {
                ErrorProvider.ReportError(ErrorCode.CanOnlyCallFunctions, Compilation, functionCall);
                return(null, false);
            }

            SymbolNode?symbol = GetExpressionSymbol(identifierExpression.Identifier,
                                                    variableIdentifierMap);

            if (symbol == null)
            {
                ErrorProvider.ReportError(ErrorCode.CantFindIdentifierInScope,
                                          Compilation,
                                          identifierExpression);
                return(null, false);
            }

            if (symbol is not FunctionSymbolNode functionSymbol)
            {
                ErrorProvider.ReportError(ErrorCode.CanOnlyCallFunctions, Compilation, functionCall);
                return(null, false);
            }

            identifierExpression.Bind(symbol);

            if (expressionContext && functionSymbol.ReturnTypeNode == null)
            {
                ErrorProvider.ReportError(ErrorCode.OnlyFunctionWithReturnTypeCanBeExpression, Compilation, functionCall);
                return(null, false);
            }

            if (functionSymbol.ParameterNodes.Count != functionCall.ArgumentNodes.Count)
            {
                ErrorProvider.ReportError(ErrorCode.WrongNumberOfArguments,
                                          Compilation,
                                          functionCall,
                                          $"Expected number of arguments: {functionSymbol.ParameterNodes.Count}",
                                          $"Provided number of arguments: {functionCall.ArgumentNodes.Count}");
                return(null, false);
            }

            for (int i = 0; i < functionSymbol.ParameterNodes.Count; i++)
            {
                TypeSymbolNode?argumentType = BindInExpression(functionCall.ArgumentNodes[i], variableIdentifierMap);

                if (argumentType == null)
                {
                    return(null, false);
                }

                if (!TypeIsCompatibleWith(argumentType,
                                          functionSymbol.ParameterNodes[i].TypeNode,
                                          functionCall.ArgumentNodes[i],
                                          out ImplicitConversionSymbolNode? conversion))
                {
                    return(null, false);
                }

                if (conversion != null)
                {
                    functionCall.ArgumentNodes[i].SpecifyImplicitConversion(conversion);
                }
            }

            functionCall.Bind(functionSymbol);

            return(functionSymbol.ReturnTypeNode, true);
        }