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 VisitEquivalenceOperator(IEquivalenceOperator node, List <TypeNode> parameterTypes)
        {
            TypeNode left  = GetType(node.Children[0], parameterTypes);
            TypeNode right = GetType(node.Children[1], parameterTypes);

            if (left.Type == right.Type)
            {
                node.Type = left.Type;
                return(new TypeNode(TypeEnum.Boolean, 0, 0));
            }
            else if (left.Type == TypeEnum.Real && right.Type == TypeEnum.Integer)
            {
                node.Type = TypeEnum.Real;
                CastToReal(node, right, 1);
                return(new TypeNode(TypeEnum.Boolean, 0, 0));
            }
            else if (left.Type == TypeEnum.Integer && right.Type == TypeEnum.Real)
            {
                node.Type = TypeEnum.Real;
                CastToReal(node, left, 0);
                return(new TypeNode(TypeEnum.Boolean, 0, 0));
            }
            else
            {
                throw new UnmatchableTypesException((Node)node, left.Type, right.Type, "expected same type");
            }
        }