public TypeNode Dispatch(ExpressionNode node, List <TypeNode> parameterTypes)
 {
     return(node switch
     {
         IBinaryNumberOperator n => _numberHelper.VisitBinaryNumOp(n, parameterTypes),
         IBinaryBooleanOperator n => _booleanHelper.VisitBinaryBoolOp(n, parameterTypes),
         IBinarySetOperator n => _setHelper.VisitBinarySetOp(n, parameterTypes),
         SubsetExpression n => _setHelper.VisitSubset(n, parameterTypes),
         SetExpression n => _setHelper.VisitSet(n, parameterTypes),
         NotExpression n => _booleanHelper.VisitNot(n, parameterTypes),
         FunctionCallExpression n => _declarationHelper.VisitFunctionCall(n, parameterTypes),
         IdentifierExpression n => _declarationHelper.VisitIdentifier(n, parameterTypes),
         IntegerLiteralExpression _ => _declarationHelper.VisitIntegerLiteral(),
         RealLiteralExpression _ => _declarationHelper.VisitRealLiteral(),
         BooleanLiteralExpression _ => _declarationHelper.VisitBooleanLiteral(),
         StringLiteralExpression _ => _declarationHelper.VisitStringLiteral(),
         EmptySetLiteralExpression _ => _declarationHelper.VisitEmptySetLiteral(),
         AdditionExpression n => _commonOperatorHelper.VisitAddition(n, parameterTypes),
         SubtractionExpression n => _commonOperatorHelper.VisitSubtraction(n, parameterTypes),
         AbsoluteValueExpression n => _commonOperatorHelper.VisitAbsoluteValue(n, parameterTypes),
         IRelationOperator n => _commonOperatorHelper.VisitRelationalOperator(n, parameterTypes),
         IEquivalenceOperator n => _commonOperatorHelper.VisitEquivalenceOperator(n, parameterTypes),
         NegativeExpression n => _numberHelper.VisitNegative(n, parameterTypes),
         ElementExpression n => _commonOperatorHelper.VisitElement(n, parameterTypes),
         ISetGraphField n => _commonOperatorHelper.VisitISetGraphField(n, parameterTypes),
         IFunctionGraphField n => _commonOperatorHelper.VisitIFunctionGraphField(n, parameterTypes),
         GraphExpression n => _commonOperatorHelper.VisitGraph(n, parameterTypes),
         AnonymousFunctionExpression n => _declarationHelper.VisitAnonymousFunction(n, parameterTypes),
         _ => throw new UnimplementedTypeCheckerException(node, "Dispatch"),
     });
        public TypeNode VisitBinaryNumOp(IBinaryNumberOperator binaryNode, List <TypeNode> parameterTypes)
        {
            TypeNode left  = _getType(binaryNode.Children[0], parameterTypes);
            TypeNode right = _getType(binaryNode.Children[1], parameterTypes);

            if (!IsNumberType(left.Type) || !IsNumberType(right.Type))
            {
                throw new UnmatchableTypesException((Node)binaryNode, left.Type, right.Type, "number");
            }

            if (left.Type != right.Type)
            {
                CastToReal(binaryNode, left, 0);
                CastToReal(binaryNode, right, 1);
                return(new TypeNode(TypeEnum.Real, 0, 0));
            }
            return(new TypeNode(left.Type, 0, 0));
        }