public Value Add(Value left, Value right)
        {
            // Convert values into literals
            left = left.AsLiteral();
            right = right.AsLiteral();

            // Convert booleans into ints
            if (ValueType.BOOL == left.Type) {
                left = new Literal((bool)left.AsValue() ? 1 : 0);
            }
            if (ValueType.BOOL == right.Type) {
                right = new Literal((bool)right.AsValue() ? 1 : 0);
            }

            var lVal = left.AsValue();
            var rVal = right.AsValue();

            // String concatenations
            if (ValueType.STRING == left.Type && ValueType.STRING == right.Type) {
                var lStr = lVal.ToString();
                var rStr = rVal.ToString();
                return new Literal(lStr + rStr);
            }
            if (ValueType.STRING == left.Type || ValueType.STRING == right.Type) {
                string msg = "Cannot implicity convert to string";
                throw new InvalidOperationException(msg);
            }

            // Arithmetic operations
            if (ValueType.INT == left.Type) {
                if (ValueType.INT == right.Type) {
                    return new Literal((int)lVal + (int)rVal);
                }
                if (ValueType.FLOAT == right.Type) {
                    return new Literal((int)lVal + (float)rVal);
                }
            }
            if (ValueType.FLOAT == left.Type) {
                if (ValueType.INT == right.Type) {
                    return new Literal((float)lVal + (int)rVal);
                }
                if (ValueType.FLOAT == right.Type) {
                    return new Literal((float)lVal + (float)rVal);
                }
            }

            // The calculator doesn't know how to handle this type
            throw new InvalidOperationException("Invalid value type");
        }
 /// <summary>
 /// Assigns the right-hand Value to the left-hand Value.
 /// </summary>
 /// <param name="left">
 /// The left-hand value.
 /// </param>
 /// <param name="right">
 /// The right-hand value
 /// </param>
 public void Assign(Value left, Value right)
 {
     if (m_calculator.CanAssign(left, right)) {
         var name = (left as Variable).Name;
         if (m_variables.ContainsKey(name)) {
             m_variables[name] = new Literal(right.AsLiteral());
         }
         else {
             string msg = "Variable has not been instantiated";
             throw new InvalidOperationException(msg);
         }
     }
     else {
         string msg = "Cannot assign value to variable";
         throw new InvalidOperationException(msg);
     }
 }
 /// <summary>
 /// Creates a copy of a literal.
 /// </summary>
 /// <param name="literal">
 /// The literal to copy.
 /// </param>
 public Literal(Literal literal)
     : base(literal.Type)
 {
     m_data = literal.m_data;
 }
        public bool Equals(Literal other)
        {
            if (null == other) {
                return false;
            }

            return m_data.Equals(other.m_data);
        }
        public Value Divide(Value left, Value right)
        {
            // Convert values into literals
            left = left.AsLiteral();
            right = right.AsLiteral();

            // Convert booleans into ints
            if (ValueType.BOOL == left.Type) {
                left = new Literal((bool)left.AsValue() ? 1 : 0);
            }
            if (ValueType.BOOL == right.Type) {
                right = new Literal((bool)right.AsValue() ? 1 : 0);
            }

            var lVal = left.AsValue();
            var rVal = right.AsValue();

            // Arithmetic operations
            if (ValueType.INT == right.Type) {
                if (0 == (int)rVal) {
                    throw new DivideByZeroException();
                }
            }
            if (ValueType.FLOAT == right.Type) {
                if (0.0f == (float)rVal) {
                    throw new DivideByZeroException();
                }
            }
            if (ValueType.INT == left.Type) {
                if (ValueType.INT == right.Type) {
                    return new Literal((int)lVal / (int)rVal);
                }
                if (ValueType.FLOAT == right.Type) {
                    return new Literal((int)lVal / (float)rVal);
                }
            }
            if (ValueType.FLOAT == left.Type) {
                if (ValueType.INT == right.Type) {
                    return new Literal((float)lVal / (int)rVal);
                }
                if (ValueType.FLOAT == right.Type) {
                    return new Literal((float)lVal / (float)rVal);
                }
            }

            // The calculator doesn't know how to handle this type
            throw new InvalidOperationException("Invalid value type");
        }
        public Value Xor(Value left, Value right)
        {
            // Convert values into literals
            left = left.AsLiteral();
            right = right.AsLiteral();

            if (ValueType.FLOAT == left.Type || ValueType.FLOAT == right.Type) {
                throw new InvalidOperationException("Invalid value type");
            }
            if (ValueType.STRING == left.Type || ValueType.STRING == right.Type) {
                throw new InvalidOperationException("Invalid value type");
            }

            if (ValueType.BOOL == left.Type && ValueType.BOOL == right.Type) {
                return new Literal(IsTrue(left) ^ IsTrue(right));
            }

            // Convert booleans into ints
            if (ValueType.BOOL == left.Type) {
                left = new Literal((bool)left.AsValue() ? 1 : 0);
            }
            if (ValueType.BOOL == right.Type) {
                right = new Literal((bool)right.AsValue() ? 1 : 0);
            }

            // Perform bitwise xor on integers
            if (ValueType.INT == left.Type && ValueType.INT == right.Type) {
                return new Literal((int)left.AsValue() ^ (int)right.AsValue());
            }

            // The calculator doesn't know how to handle this type
            throw new InvalidOperationException("Invalid value type");
        }
        public Value Not(Value value)
        {
            value = value.AsLiteral();
            if (ValueType.BOOL == value.Type) {
                value = new Literal((bool)value.AsValue() ? 1 : 0);
            }

            var obj = value.AsValue();

            if (ValueType.INT == value.Type) {
                return new Literal(0 == (int)obj);
            }
            if (ValueType.FLOAT == value.Type) {
                return new Literal(0.0f == (float)obj);
            }
            if (ValueType.STRING == value.Type) {
                return new Literal(0 == ((string)obj).Length);
            }

            // The calculator doesn't know how to handle this type
            throw new InvalidOperationException("Invalid value type");
        }
        public Value LessThan(Value left, Value right)
        {
            // Convert values into literals
            left = left.AsLiteral();
            right = right.AsLiteral();

            // Convert booleans into ints
            if (ValueType.BOOL == left.Type) {
                left = new Literal((bool)left.AsValue() ? 1 : 0);
            }
            if (ValueType.BOOL == right.Type) {
                right = new Literal((bool)right.AsValue() ? 1 : 0);
            }

            var lVal = left.AsValue();
            var rVal = right.AsValue();

            // String comparison
            if (ValueType.STRING == left.Type && ValueType.STRING == right.Type) {
                string lStr = (string)lVal;
                string rStr = (string)rVal;
                int max = lStr.Length < rStr.Length ? rStr.Length : lStr.Length;

                for (int i = 0; i < max; ++i) {
                    if (i >= lStr.Length && lStr.Length != rStr.Length) {
                        return new Literal(true);
                    }
                    if (i >= rStr.Length && lStr.Length != rStr.Length) {
                        return new Literal(false);
                    }

                    if (lStr[i] < rStr[i]) {
                        return new Literal(true);
                    }
                    else if (lStr[i] > rStr[i]) {
                        return new Literal(false);
                    }
                }

                // Strings are equal
                return new Literal(false);
            }

            // Arithmetic operations
            if (ValueType.INT == left.Type) {
                if (ValueType.INT == right.Type) {
                    return new Literal((int)lVal < (int)rVal);
                }
                if (ValueType.FLOAT == right.Type) {
                    return new Literal((int)lVal < (float)rVal);
                }
            }
            if (ValueType.FLOAT == left.Type) {
                if (ValueType.INT == right.Type) {
                    return new Literal((float)lVal < (int)rVal);
                }
                if (ValueType.FLOAT == right.Type) {
                    return new Literal((float)lVal < (float)rVal);
                }
            }

            // The calculator doesn't know how to handle this type
            throw new InvalidOperationException("Invalid value type");
        }