/// <summary>Runs the Operator on two operands.</summary>
        /// <param name="left">The left operand.</param>
        /// <param name="right">The right operand.</param>
        /// <param name="vars">The local variable storage.</param>
        /// <param name="context">An object representing context.</param>
        public CalcValue Run(CalcObject left, CalcObject right, CLLocalStore vars = null, CLContextProvider context = null)
        {
            // If the operator is value-based, we'll automatically convert expressions.
            if (ValueBasedLeft)
            {
                left = left.GetValue(vars, context);
            }
            if (ValueBasedRight)
            {
                right = right.GetValue(vars, context);
            }

            // Now get the func.
            CLBinaryOperatorFunc func = this[left.GetType(), right.GetType()];

            // If it's null, we'll throw an exception.
            if (func == null)
            {
                throw new CLException(
                          "Binary operator " + Symbol + " doesn't support parameters " + left.GetType().Name + " and " + right.GetType().Name
                          );
            }

            // Now let's run it.
            return(func(left, right, vars, context));
        }
        /// <summary>
        /// Adds a new function for the given types.
        /// </summary>
        /// <param name="left">The type of the left operand.</param>
        /// <param name="right">The type of the right operand.</param>
        /// <param name="func">
        /// The function that handles those operands.
        /// </param>
        /// <param name="replaceChildren">
        /// Iff <c>true</c>, the functions that handle types more derived than
        /// <c>left</c> and <c>right</c> should be removed from this operator.
        /// </param>
        public virtual void AddFunction(Type left, Type right, CLBinaryOperatorFunc func, bool replaceChildren = true)
        {
            Dictionary <Type, CLBinaryOperatorFunc> subDict;

            if (!Functions.ContainsKey(left))
            {
                subDict         = new Dictionary <Type, CLBinaryOperatorFunc>();
                Functions[left] = subDict;
            }
            else
            {
                subDict = Functions[left];
            }

            subDict[right] = func;

            // Now replace all the child types if necessary.
            if (replaceChildren)
            {
                foreach (Type leftTest in Functions.Keys)
                {
                    if (leftTest.IsSubclassOf(left) || leftTest == left)
                    {
                        foreach (Type rightTest in Functions[leftTest].Keys)
                        {
                            if (rightTest.IsSubclassOf(right) || (rightTest == right && leftTest != left))
                            {
                                Functions[left].Remove(right);
                            }
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Throws an <c>InvalidOperationException</c>. To add a function, go
 /// through the <c>Parent</c> instead.
 /// </summary>
 public override void AddFunction(Type left, Type right, CLBinaryOperatorFunc func, bool replaceChildren)
 {
     throw new InvalidOperationException("For a CLComparisonOperator, functions must be added through the set.");
 }