public bool CanAssign(Value left, Value right)
        {
            // Check if the left value is a variable
            if (!(left is Variable)) {
                var msg = "Cannot assign a value to a non-variable type";
                throw new InvalidOperationException(msg);
            }

            return true;
        }
        public Value And(Value left, Value right)
        {
            // Convert values into literals
            left = left.AsLiteral();
            right = right.AsLiteral();

            if (IsTrue(left)) {
                return new Literal((Literal)right);
            }
            else {
                return new Literal((Literal)left);
            }
        }
        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);
     }
 }
        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");
        }
 public Value GreaterThan(Value left, Value right)
 {
     return m_calculator.GreaterThan(left, right);
 }
 public Value Multiply(Value left, Value right)
 {
     return m_calculator.Multiply(left, right);
 }
 public bool CanAssign(Value left, Value right)
 {
     return m_calculator.CanAssign(left, right);
 }
 public Value And(Value left, Value right)
 {
     return m_calculator.And(left, right);
 }
 public Value Xor(Value left, Value right)
 {
     return m_calculator.Xor(left, right);
 }
 public Value Subtract(Value left, Value right)
 {
     return m_calculator.Subtract(left, right);
 }
 public Value Not(Value value)
 {
     return m_calculator.Not(value);
 }
        private bool IsTrue(Value value)
        {
            switch (value.Type) {
                case ValueType.BOOL:
                    if (false == (bool)value.AsValue()) {
                        return false;
                    }
                    break;
                case ValueType.INT:
                    if (0 == (int)value.AsValue()) {
                        return false;
                    }
                    break;
                case ValueType.FLOAT:
                    if (0.0f == (float)value.AsValue()) {
                        return false;
                    }
                    break;
                case ValueType.STRING:
                    if ("" == (string)value.AsValue()) {
                        return false;
                    }
                    break;
                default:
                    throw new InvalidOperationException("Invalid value type");
            }

            return true;
        }
 public Value Divide(Value left, Value right)
 {
     return m_calculator.Divide(left, right);
 }
 public Value EqualTo(Value left, Value right)
 {
     return m_calculator.EqualTo(left, right);
 }
        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 LessThan(Value left, Value right)
 {
     return m_calculator.LessThan(left, right);
 }