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