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 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); }
public bool TryGetTypeSymbol(TypeSpecNode?typeSpec, out TypeSymbolNode?typeSymbol) { if (typeSpec == null) { typeSymbol = null; return(true); } if (typeSpec is IdentifierTypeSpecNode identifierTypeSpecNode) { if (typeIdentifierMap.TryGet(identifierTypeSpecNode.Identifier, out typeSymbol)) { identifierTypeSpecNode.Bind(typeSymbol); return(true); } return(false); } else { Debug.Fail(message: null); typeSymbol = null; return(false); } }
internal VariableSymbolNode(string identifier, TypeSymbolNode?typeNode, bool isReadOnly, int lineNumber, int index) : base(identifier, lineNumber, index) { TypeNode = typeNode; IsReadOnly = isReadOnly; }
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); }
internal FunctionSymbolNode(string name, IEnumerable <ParameterSymbolNode>?parameters, TypeSymbolNode?returnType, int lineNumber, int index) : base(name, lineNumber, index) { ParameterNodes = parameters.MakeReadOnly(); ReturnTypeNode = returnType; }
internal FrameworkFunctionSymbolNode(string name, IEnumerable <ParameterSymbolNode> parameters, TypeSymbolNode?returnType, CodeGenerationInformation codeGenerationInfo, int lineNumber, int index) : base(name, parameters, returnType, lineNumber, index) { CodeGenerationInfo = codeGenerationInfo; }
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); }
public VariableSymbolNode CreateVariable(TypeSymbolNode?typeSymbol) { VariableSymbolNode variable = new VariableSymbolNode(VariableIdentifier, typeSymbol, IsReadOnly, VariableIdentifierNode.LineNumber, VariableIdentifierNode.Index); VariableIdentifierNode = new BoundIdentifierNode(VariableIdentifier, variable, VariableIdentifierNode.LineNumber, VariableIdentifierNode.Index) { ParentNode = this }; return(variable); }
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); }
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); }
public bool TryGetTypeSymbol(FrameworkType frameworkType, [NotNullWhen(true)] out TypeSymbolNode?typeSymbol) { return(typeIdentifierMap.TryGet(frameworkType, out typeSymbol)); }
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); }