コード例 #1
0
        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);
        }
コード例 #2
0
        private bool BindInLoopControlStatement(LoopControlStatementNode loopControlStatement)
        {
            ushort level = loopControlStatement.Level;

            Node?parent = loopControlStatement;

            while (level > 0)
            {
                parent = parent.ParentNode;

                switch (parent)
                {
                case null:
                    ErrorProvider.ReportError(ErrorCode.LoopControlStatementNotThatDeep,
                                              Compilation,
                                              loopControlStatement);
                    return(false);

                case ILoopStatementNode:
                    level--;
                    break;
                }
            }

            ILoopStatementNode?loop = parent as ILoopStatementNode;

            Debug.Assert(loop != null);

            loopControlStatement.SetControlledLoop(loop);

            return(true);
        }
コード例 #3
0
        public TypeSpecNode?ParseNextType(ref int index)
        {
            if (Lexemes.TryGet(index) is not IdentifierLexeme identifierLexeme)
            {
                ErrorProvider.ReportError(ErrorCode.ExpectedIdentifier,
                                          code,
                                          Lexemes[index]);
                return(null);
            }

            index++;
            return(new IdentifierTypeSpecNode(identifierLexeme.Content, identifierLexeme.LineNumber, identifierLexeme.Index));
        }
コード例 #4
0
        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);
        }
コード例 #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);
        }
コード例 #6
0
ファイル: ProgramParser.cs プロジェクト: Phantonia/Krypton
        internal ConstantDeclarationNode?ParseConstantDeclaration()
        {
            int lineNumber = Lexemes[index].LineNumber;
            int nodeIndex  = Lexemes[index].Index;

            index++;

            if (Lexemes[index] is not IdentifierLexeme identifier)
            {
                ErrorProvider.ReportError(ErrorCode.ExpectedIdentifier,
                                          code,
                                          Lexemes[index]);
                return(null);
            }

            index++;

            TypeSpecNode?type = null;

            if (Lexemes[index] is KeywordLexeme {
                Keyword : ReservedKeyword.As
            })
コード例 #7
0
        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);
            }
        }
コード例 #8
0
ファイル: Lexer.cs プロジェクト: Phantonia/Krypton
        public LexemeCollection?LexAll()
        {
            LexemeCollection collection = new();

            Lexeme?nextLexeme = NextLexeme();

            while (nextLexeme != null)
            {
                if (nextLexeme is InvalidLexeme invalidLexeme)
                {
                    ErrorProvider.ReportError(invalidLexeme.ErrorCode, Code, invalidLexeme);
                    return(null);
                }

                collection.Add(nextLexeme);

                nextLexeme = NextLexeme();
            }

            collection.Add(new EndOfFileLexeme(lineNumber, Code.Length));

            return(collection);
        }
コード例 #9
0
        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);
        }
コード例 #10
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);
        }
コード例 #11
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);
        }
コード例 #12
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);
        }
コード例 #13
0
        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);
        }