Beispiel #1
0
        protected override void CoreExpandTemplate(ITemplatingContext templatingContext)
        {
            const uint MAX_ITERATIONS_INFINITE_LOOP_CHECK = 999999;
            string varIx;
            uint index = 1; // one-based
            object value;
            bool shouldLoop;
            DynamicWildcardTokenReplacementStrategy dynamicWildcardTokenReplacementStrategy;

            if ((object)templatingContext == null)
                throw new ArgumentNullException("templatingContext");

            dynamicWildcardTokenReplacementStrategy = templatingContext.GetDynamicWildcardTokenReplacementStrategy();

            varIx = templatingContext.Tokenizer.ExpandTokens(this.VarIx, dynamicWildcardTokenReplacementStrategy);

            if (!DataType.IsNullOrWhiteSpace(varIx))
            {
                new AllocConstruct()
                {
                    Token = varIx
                }.ExpandTemplate(templatingContext);
            }

            if ((object)this.Initializer != null)
                value = this.Initializer.EvaluateExpression(templatingContext);

            while (true)
            {
                if (index > MAX_ITERATIONS_INFINITE_LOOP_CHECK)
                    throw new InvalidOperationException(string.Format("The for construct has exceeded the maximun number of iterations '{0}'; this is an infinite loop prevention mechansim.", MAX_ITERATIONS_INFINITE_LOOP_CHECK));

                if ((object)this.Condition != null)
                    value = this.Condition.EvaluateExpression(templatingContext);
                else
                    value = false;

                if ((object)value != null && !(value is bool) && !(value is bool?))
                    throw new InvalidOperationException(string.Format("The for construct condition expression has evaluated to a non-null value with an unsupported type '{0}'; only '{1}' and '{2}' types are supported.", value.GetType().FullName, typeof(bool).FullName, typeof(bool?).FullName));

                shouldLoop = ((bool)(value ?? false));

                if (!shouldLoop)
                    break;

                if (!DataType.IsNullOrWhiteSpace(varIx))
                {
                    ExpressionContainerConstruct expressionContainerConstruct;
                    ValueConstruct valueConstruct;

                    expressionContainerConstruct = new ExpressionContainerConstruct();

                    valueConstruct = new ValueConstruct()
                                     {
                                         Type = typeof(int).FullName,
                                         __ = index
                                     };

                    expressionContainerConstruct.Content = valueConstruct;

                    new AssignConstruct()
                    {
                        Token = varIx,
                        Expression = expressionContainerConstruct
                    }.ExpandTemplate(templatingContext);
                }

                if ((object)this.Body != null)
                    this.Body.ExpandTemplate(templatingContext);

                if ((object)this.Iterator != null)
                    value = this.Iterator.EvaluateExpression(templatingContext);

                index++;
            }

            if (!DataType.IsNullOrWhiteSpace(varIx))
            {
                new FreeConstruct()
                {
                    Token = varIx
                }.ExpandTemplate(templatingContext);
            }
        }
Beispiel #2
0
        protected override void CoreExpandTemplate(ITemplatingContext templatingContext)
        {
            string @in, varCt, varItem, varIx;
            uint count = 0, index = 1; // one-based
            IEnumerable values;
            object obj;
            DynamicWildcardTokenReplacementStrategy dynamicWildcardTokenReplacementStrategy;

            if ((object)templatingContext == null)
                throw new ArgumentNullException("templatingContext");

            dynamicWildcardTokenReplacementStrategy = templatingContext.GetDynamicWildcardTokenReplacementStrategy();

            @in = templatingContext.Tokenizer.ExpandTokens(this.In, dynamicWildcardTokenReplacementStrategy);
            varItem = templatingContext.Tokenizer.ExpandTokens(this.VarItem, dynamicWildcardTokenReplacementStrategy);
            varCt = templatingContext.Tokenizer.ExpandTokens(this.VarCt, dynamicWildcardTokenReplacementStrategy);
            varIx = templatingContext.Tokenizer.ExpandTokens(this.VarIx, dynamicWildcardTokenReplacementStrategy);

            if (!DataType.IsNullOrWhiteSpace(varItem))
            {
                new AllocConstruct()
                {
                    Token = varItem
                }.ExpandTemplate(templatingContext);
            }

            if (!DataType.IsNullOrWhiteSpace(varCt))
            {
                new AllocConstruct()
                {
                    Token = varCt
                }.ExpandTemplate(templatingContext);
            }

            if (!DataType.IsNullOrWhiteSpace(varIx))
            {
                new AllocConstruct()
                {
                    Token = varIx
                }.ExpandTemplate(templatingContext);
            }

            if (!dynamicWildcardTokenReplacementStrategy.GetByPath(@in, out obj))
                throw new InvalidOperationException(string.Format("The facet name '{0}' was not found on the target model.", @in));

            if ((object)obj == null)
                return;

            if (!(obj is IEnumerable))
                throw new InvalidOperationException(string.Format("The in expression the for-each construct is not assignable to type '{0}'.", typeof(IEnumerable).FullName));

            values = (IEnumerable)obj;
            obj = null; // not needed

            if ((object)this.Filter != null)
            {
                ArrayList temp;
                bool shouldFilter;

                temp = new ArrayList();

                if ((object)values != null)
                {
                    foreach (object value in values)
                    {
                        templatingContext.IteratorModels.Push(value);

                        obj = this.Filter.EvaluateExpression(templatingContext);

                        templatingContext.IteratorModels.Pop();

                        if ((object)obj != null && !(obj is bool) && !(obj is bool?))
                            throw new InvalidOperationException(string.Format("The for-each construct filter expression has evaluated to a non-null value with an unsupported type '{0}'; only '{1}' and '{2}' types are supported.", value.GetType().FullName, typeof(bool).FullName, typeof(bool?).FullName));

                        shouldFilter = !((bool)(obj ?? true));

                        if (!shouldFilter)
                        {
                            count++;
                            temp.Add(value);
                        }
                    }
                }

                values = temp;
            }
            else
            {
                if ((object)values != null)
                {
                    foreach (object value in values)
                        count++;
                }
            }

            if ((object)this.Sort != null)
                values = this.Sort.EvaluateSort(templatingContext, values);

            if (!DataType.IsNullOrWhiteSpace(varCt))
            {
                ExpressionContainerConstruct expressionContainerConstruct;
                ValueConstruct valueConstruct;

                expressionContainerConstruct = new ExpressionContainerConstruct();

                valueConstruct = new ValueConstruct()
                                 {
                                     Type = typeof(int).FullName,
                                     __ = count
                                 };

                expressionContainerConstruct.Content = valueConstruct;

                new AssignConstruct()
                {
                    Token = varCt,
                    Expression = expressionContainerConstruct
                }.ExpandTemplate(templatingContext);
            }

            if ((object)values != null)
            {
                foreach (object value in values)
                {
                    if (!DataType.IsNullOrWhiteSpace(varItem))
                    {
                        ExpressionContainerConstruct expressionContainerConstruct;
                        ValueConstruct valueConstruct;

                        expressionContainerConstruct = new ExpressionContainerConstruct();

                        valueConstruct = new ValueConstruct()
                                         {
                                             __ = value
                                         };

                        expressionContainerConstruct.Content = valueConstruct;

                        new AssignConstruct()
                        {
                            Token = varItem,
                            Expression = expressionContainerConstruct
                        }.ExpandTemplate(templatingContext);
                    }

                    if (!DataType.IsNullOrWhiteSpace(varIx))
                    {
                        ExpressionContainerConstruct expressionContainerConstruct;
                        ValueConstruct valueConstruct;

                        expressionContainerConstruct = new ExpressionContainerConstruct();

                        valueConstruct = new ValueConstruct()
                                         {
                                             Type = typeof(int).FullName,
                                             __ = index
                                         };

                        expressionContainerConstruct.Content = valueConstruct;

                        new AssignConstruct()
                        {
                            Token = varIx,
                            Expression = expressionContainerConstruct
                        }.ExpandTemplate(templatingContext);
                    }

                    templatingContext.IteratorModels.Push(value);

                    if ((object)this.Body != null)
                        this.Body.ExpandTemplate(templatingContext);

                    templatingContext.IteratorModels.Pop();

                    index++;
                }

                if (!DataType.IsNullOrWhiteSpace(varIx))
                {
                    new FreeConstruct()
                    {
                        Token = varIx
                    }.ExpandTemplate(templatingContext);
                }

                if (!DataType.IsNullOrWhiteSpace(varCt))
                {
                    new FreeConstruct()
                    {
                        Token = varCt
                    }.ExpandTemplate(templatingContext);
                }

                if (!DataType.IsNullOrWhiteSpace(varItem))
                {
                    new FreeConstruct()
                    {
                        Token = varItem
                    }.ExpandTemplate(templatingContext);
                }
            }
        }
        protected override void CoreExpandTemplate(ITemplatingContext templatingContext)
        {
            string name;
            DynamicWildcardTokenReplacementStrategy dynamicWildcardTokenReplacementStrategy;

            if ((object)templatingContext == null)
                throw new ArgumentNullException("templatingContext");

            dynamicWildcardTokenReplacementStrategy = templatingContext.GetDynamicWildcardTokenReplacementStrategy();

            name = templatingContext.Tokenizer.ExpandTokens(this.Name, dynamicWildcardTokenReplacementStrategy);

            if (!DataType.IsNullOrWhiteSpace(name))
            {
                new AllocConstruct()
                {
                    Token = "#OutputScopeName"
                }.ExpandTemplate(templatingContext);
            }

            if (!DataType.IsNullOrWhiteSpace(name))
            {
                ExpressionContainerConstruct expressionContainerConstruct;
                ValueConstruct valueConstruct;

                expressionContainerConstruct = new ExpressionContainerConstruct();

                valueConstruct = new ValueConstruct()
                                 {
                                     Type = typeof(string).FullName,
                                     __ = name
                                 };

                expressionContainerConstruct.Content = valueConstruct;

                new AssignConstruct()
                {
                    Token = "#OutputScopeName",
                    Expression = expressionContainerConstruct
                }.ExpandTemplate(templatingContext);
            }

            templatingContext.Output.LogTextWriter.WriteLine("['{0:O}' (UTC)]\tEntering output scope '{1}'.", DateTime.UtcNow, name);
            templatingContext.Output.EnterScope(name);

            if ((object)this.Items != null)
            {
                foreach (ITemplateMechanism templateMechanism in this.Items)
                    templateMechanism.ExpandTemplate(templatingContext);
            }

            templatingContext.Output.LeaveScope(name);
            templatingContext.Output.LogTextWriter.WriteLine("['{0:O}' (UTC)]\tLeaving output scope '{1}'.", DateTime.UtcNow, name);

            if (!DataType.IsNullOrWhiteSpace(name))
            {
                new FreeConstruct()
                {
                    Token = "#OutputScopeName"
                }.ExpandTemplate(templatingContext);
            }
        }
        protected override object CoreEvaluateExpression(ITemplatingContext templatingContext)
        {
            DynamicWildcardTokenReplacementStrategy dynamicWildcardTokenReplacementStrategy;
            object leftObj = null, rightObj = null;
            Type leftType, rightType;
            Func<object> onDemandRightExpressionEvaluator;

            Type[] numericTypes = new Type[]
                                  {
                                      typeof(Byte),
                                      typeof(Int16),
                                      typeof(Int32),
                                      typeof(Int64),
                                      typeof(SByte),
                                      typeof(UInt16),
                                      typeof(UInt32),
                                      typeof(UInt64),
                                      typeof(Single),
                                      typeof(Double),
                                      typeof(Decimal),
                                      typeof(Byte?),
                                      typeof(Int16?),
                                      typeof(Int32?),
                                      typeof(Int64?),
                                      typeof(SByte?),
                                      typeof(UInt16?),
                                      typeof(UInt32?),
                                      typeof(UInt64?),
                                      typeof(Single?),
                                      typeof(Double?),
                                      typeof(Decimal?)
                                  };

            if ((object)templatingContext == null)
                throw new ArgumentNullException("templatingContext");

            dynamicWildcardTokenReplacementStrategy = templatingContext.GetDynamicWildcardTokenReplacementStrategy(false);

            if ((object)this.LeftExpression != null)
                leftObj = this.LeftExpression.EvaluateExpression(templatingContext);

            onDemandRightExpressionEvaluator = () =>
                                               {
                                                   if ((object)this.RightExpression != null)
                                                       return this.RightExpression.EvaluateExpression(templatingContext);
                                                   else
                                                       return null;
                                               };

            if ((object)leftObj == null)
                return null;

            leftType = leftObj.GetType();

            switch (this.BinaryOperator)
            {
                case BinaryOperator.Eq:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs == rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs == rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs == rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs == rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs == rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs == rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs == rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs == rhs;
                        }
                    }
                    else if (typeof(IComparable).IsAssignableFrom(leftType) &&
                             typeof(IComparable).IsAssignableFrom(rightType) &&
                             rightType.IsAssignableFrom(leftType) &&
                             leftType.IsAssignableFrom(rightType))
                    {
                        IComparable lhs, rhs;
                        int crv;

                        lhs = leftObj.ChangeType<IComparable>();
                        rhs = rightObj.ChangeType<IComparable>();

                        if ((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message |((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))");

                        return crv == 0;
                    }

                    break;
                }
                case BinaryOperator.Ne:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs != rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs != rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs != rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs != rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs != rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs != rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs != rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs != rhs;
                        }
                    }
                    else if (typeof(IComparable).IsAssignableFrom(leftType) &&
                             typeof(IComparable).IsAssignableFrom(rightType) &&
                             rightType.IsAssignableFrom(leftType) &&
                             leftType.IsAssignableFrom(rightType))
                    {
                        IComparable lhs, rhs;
                        int crv;

                        lhs = leftObj.ChangeType<IComparable>();
                        rhs = rightObj.ChangeType<IComparable>();

                        if ((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message |((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))");

                        return crv != 0;
                    }

                    break;
                }
                case BinaryOperator.Lt:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs < rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs < rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs < rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs < rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs < rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs < rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs < rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs < rhs;
                        }
                    }
                    else if (typeof(IComparable).IsAssignableFrom(leftType) &&
                             typeof(IComparable).IsAssignableFrom(rightType) &&
                             rightType.IsAssignableFrom(leftType) &&
                             leftType.IsAssignableFrom(rightType))
                    {
                        IComparable lhs, rhs;
                        int crv;

                        lhs = leftObj.ChangeType<IComparable>();
                        rhs = rightObj.ChangeType<IComparable>();

                        if ((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message |((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))");

                        return crv < 0;
                    }

                    break;
                }
                case BinaryOperator.Le:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs <= rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs <= rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs <= rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs <= rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs <= rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs <= rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs <= rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs <= rhs;
                        }
                    }
                    else if (typeof(IComparable).IsAssignableFrom(leftType) &&
                             typeof(IComparable).IsAssignableFrom(rightType) &&
                             rightType.IsAssignableFrom(leftType) &&
                             leftType.IsAssignableFrom(rightType))
                    {
                        IComparable lhs, rhs;
                        int crv;

                        lhs = leftObj.ChangeType<IComparable>();
                        rhs = rightObj.ChangeType<IComparable>();

                        if ((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message |((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))");

                        return crv <= 0;
                    }

                    break;
                }
                case BinaryOperator.Gt:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs > rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs > rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs > rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs > rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs > rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs > rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs > rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs > rhs;
                        }
                    }
                    else if (typeof(IComparable).IsAssignableFrom(leftType) &&
                             typeof(IComparable).IsAssignableFrom(rightType) &&
                             rightType.IsAssignableFrom(leftType) &&
                             leftType.IsAssignableFrom(rightType))
                    {
                        IComparable lhs, rhs;
                        int crv;

                        lhs = leftObj.ChangeType<IComparable>();
                        rhs = rightObj.ChangeType<IComparable>();

                        if ((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message |((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))");

                        return crv > 0;
                    }

                    break;
                }
                case BinaryOperator.Ge:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs >= rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs >= rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs >= rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs >= rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs >= rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs >= rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs >= rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs >= rhs;
                        }
                    }
                    else if (typeof(IComparable).IsAssignableFrom(leftType) &&
                             typeof(IComparable).IsAssignableFrom(rightType) &&
                             rightType.IsAssignableFrom(leftType) &&
                             leftType.IsAssignableFrom(rightType))
                    {
                        IComparable lhs, rhs;
                        int crv;

                        lhs = leftObj.ChangeType<IComparable>();
                        rhs = rightObj.ChangeType<IComparable>();

                        if ((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message |((crv = lhs.CompareTo(rightObj)) != (rhs.CompareTo(leftObj) * -1))");

                        return crv >= 0;
                    }

                    break;
                }
                case BinaryOperator.Add:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs + rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs + rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs + rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs + rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs + rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs + rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs + rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs + rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Sub:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs - rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs - rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs - rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs - rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs - rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs - rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs - rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs - rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Mul:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs * rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs * rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs * rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs * rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs * rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs * rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs * rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs * rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Div:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs / rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs / rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs / rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs / rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs / rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs / rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs / rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs / rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Mod:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(Decimal) || leftType == typeof(Decimal?) ||
                            rightType == typeof(Decimal) || rightType == typeof(Decimal?))
                        {
                            if (leftType != typeof(Single) && leftType != typeof(Single?) &&
                                rightType != typeof(Single) && rightType != typeof(Single?) &&
                                leftType != typeof(Double) && leftType != typeof(Double?) &&
                                rightType != typeof(Double) && rightType != typeof(Double?))
                            {
                                Decimal lhs, rhs;

                                lhs = leftObj.ChangeType<Decimal>();
                                rhs = rightObj.ChangeType<Decimal>();

                                return lhs % rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Double) || leftType == typeof(Double?) ||
                                 rightType == typeof(Double) || rightType == typeof(Double?))
                        {
                            Double lhs, rhs;

                            lhs = leftObj.ChangeType<Double>();
                            rhs = rightObj.ChangeType<Double>();

                            return lhs % rhs;
                        }
                        else if (leftType == typeof(Single) || leftType == typeof(Single?) ||
                                 rightType == typeof(Single) || rightType == typeof(Single?))
                        {
                            Single lhs, rhs;

                            lhs = leftObj.ChangeType<Single>();
                            rhs = rightObj.ChangeType<Single>();

                            return lhs % rhs;
                        }
                        else if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                                 rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs % rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs % rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs % rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs % rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs % rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Band:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                            rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs & rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs & rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs & rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs & rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs & rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Bor:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                            rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs | rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs | rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs | rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs | rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs | rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Bxor:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if (leftType == typeof(UInt64) || leftType == typeof(UInt64?) ||
                            rightType == typeof(UInt64) || rightType == typeof(UInt64?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?) &&
                                leftType != typeof(Int64) && leftType != typeof(Int64?) &&
                                rightType != typeof(Int64) && rightType != typeof(Int64?))
                            {
                                UInt64 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt64>();
                                rhs = rightObj.ChangeType<UInt64>();

                                return lhs ^ rhs;
                            }
                            else
                            {
                                // bad
                            }
                        }
                        else if (leftType == typeof(Int64) || leftType == typeof(Int64?) ||
                                 rightType == typeof(Int64) || rightType == typeof(Int64?))
                        {
                            Int64 lhs, rhs;

                            lhs = leftObj.ChangeType<Int64>();
                            rhs = rightObj.ChangeType<Int64>();

                            return lhs ^ rhs;
                        }
                        else if (leftType == typeof(UInt32) || leftType == typeof(UInt32?) ||
                                 rightType == typeof(UInt32) || rightType == typeof(UInt32?))
                        {
                            if (leftType != typeof(SByte) && leftType != typeof(SByte?) &&
                                rightType != typeof(SByte) && rightType != typeof(SByte?) &&
                                leftType != typeof(Int16) && leftType != typeof(Int16?) &&
                                rightType != typeof(Int16) && rightType != typeof(Int16?) &&
                                leftType != typeof(Int32) && leftType != typeof(Int32?) &&
                                rightType != typeof(Int32) && rightType != typeof(Int32?))
                            {
                                UInt32 lhs, rhs;

                                lhs = leftObj.ChangeType<UInt32>();
                                rhs = rightObj.ChangeType<UInt32>();

                                return lhs ^ rhs;
                            }
                            else
                            {
                                Int64 lhs, rhs;

                                lhs = leftObj.ChangeType<Int64>();
                                rhs = rightObj.ChangeType<Int64>();

                                return lhs ^ rhs;
                            }
                        }
                        else
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs ^ rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Bls:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if ((leftType == typeof(Int32) || leftType == typeof(Int32?)) &&
                            (rightType == typeof(Int32) || rightType == typeof(Int32?)))
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs << rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Brs:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if ((leftType == typeof(Int32) || leftType == typeof(Int32?)) &&
                            (rightType == typeof(Int32) || rightType == typeof(Int32?)))
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs >> rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Bsr:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if ((leftType == typeof(Int32) || leftType == typeof(Int32?)) &&
                            (rightType == typeof(Int32) || rightType == typeof(Int32?)))
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs >> rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Bur:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (numericTypes.Count(t => t == leftType) == 1 && numericTypes.Count(t => t == rightType) == 1)
                    {
                        if ((leftType == typeof(Int32) || leftType == typeof(Int32?)) &&
                            (rightType == typeof(Int32) || rightType == typeof(Int32?)))
                        {
                            Int32 lhs, rhs;

                            lhs = leftObj.ChangeType<Int32>();
                            rhs = rightObj.ChangeType<Int32>();

                            return lhs >> rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.StrLk:
                {
                    if (leftType == typeof(String))
                    {
                        rightObj = onDemandRightExpressionEvaluator();

                        if ((object)rightObj == null)
                            return false;

                        rightType = rightObj.GetType();

                        if (rightType == typeof(String))
                        {
                            string lhs, rhs;

                            lhs = leftObj.ChangeType<string>();
                            rhs = rightObj.ChangeType<string>();

                            return lhs.Contains(rhs);
                        }
                        /*else
                        {
                            string lhs, rhs;

                            lhs = leftObj.SafeToString();
                            rhs = rightObj.SafeToString();

                            return lhs.Contains(rhs);
                        }*/
                    }

                    break;
                }
                case BinaryOperator.And:
                {
                    if (leftType == typeof(Boolean) || leftType == typeof(Boolean?))
                    {
                        bool lhs;

                        lhs = leftObj.ChangeType<bool>();

                        // short circuit evaluate
                        if (!lhs)
                            return false;

                        rightObj = onDemandRightExpressionEvaluator();

                        if ((object)rightObj == null)
                            return null;

                        rightType = rightObj.GetType();

                        if (rightType == typeof(Boolean) || rightType == typeof(Boolean?))
                        {
                            bool rhs;

                            rhs = rightObj.ChangeType<bool>();

                            return rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Or:
                {
                    if (leftType == typeof(Boolean) || leftType == typeof(Boolean?))
                    {
                        bool lhs;

                        lhs = leftObj.ChangeType<bool>();

                        // short circuit evaluate
                        if (lhs)
                            return true;

                        rightObj = onDemandRightExpressionEvaluator();

                        if ((object)rightObj == null)
                            return null;

                        rightType = rightObj.GetType();

                        if (rightType == typeof(Boolean) || rightType == typeof(Boolean?))
                        {
                            bool rhs;

                            rhs = rightObj.ChangeType<bool>();

                            return rhs;
                        }
                    }

                    break;
                }
                case BinaryOperator.Xor:
                {
                    if (leftType == typeof(Boolean) || leftType == typeof(Boolean?))
                    {
                        bool lhs;

                        lhs = leftObj.ChangeType<bool>();

                        // no short circuit evaluate possible here

                        rightObj = onDemandRightExpressionEvaluator();

                        if ((object)rightObj == null)
                            return null;

                        rightType = rightObj.GetType();

                        if (rightType == typeof(Boolean) || rightType == typeof(Boolean?))
                        {
                            bool rhs;

                            rhs = rightObj.ChangeType<bool>();

                            return (lhs && !rhs) || (rhs && !lhs);
                        }
                    }

                    break;
                }
                case BinaryOperator.ObjAs:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (rightType == typeof(String))
                    {
                        string rhs;

                        rhs = rightObj.ChangeType<string>();

                        if (DataType.IsWhiteSpace(rhs))
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message | DataType.IsNullOrWhiteSpace(rhs)");

                        rightType = Type.GetType(rhs, false);

                        if ((object)rightType == null)
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message | Type.GetType");

                        return DataType.ChangeType(leftObj, rightType);
                    }

                    break;
                }
                case BinaryOperator.Parse:
                {
                    if (leftType == typeof(String))
                    {
                        rightObj = onDemandRightExpressionEvaluator();

                        if ((object)rightObj == null)
                            return null;

                        rightType = rightObj.GetType();

                        if (rightType == typeof(String))
                        {
                            string lhs, rhs;
                            object result;

                            lhs = leftObj.ChangeType<string>();
                            rhs = rightObj.ChangeType<string>();

                            if (DataType.IsWhiteSpace(rhs))
                                throw new InvalidOperationException("TODO (enhancement): add meaningful message | DataType.IsNullOrWhiteSpace(rhs)");

                            rightType = Type.GetType(rhs, false);

                            if ((object)rightType == null)
                                throw new InvalidOperationException("TODO (enhancement): add meaningful message | Type.GetType");

                            if (!DataType.TryParse(rightType, lhs, out result))
                                throw new InvalidOperationException("TODO (enhancement): add meaningful message | DataType.TryParse");

                            return result;
                        }
                    }

                    break;
                }
                case BinaryOperator.ObjIs:
                {
                    rightObj = onDemandRightExpressionEvaluator();

                    if ((object)rightObj == null)
                        return null;

                    rightType = rightObj.GetType();

                    if (rightType == typeof(String))
                    {
                        string rhs;

                        rhs = rightObj.ChangeType<string>();

                        if (DataType.IsWhiteSpace(rhs))
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message | DataType.IsNullOrWhiteSpace(rhs)");

                        rightType = Type.GetType(rhs, false);

                        if ((object)rightType == null)
                            throw new InvalidOperationException("TODO (enhancement): add meaningful message | Type.GetType");

                        return rightType.IsAssignableFrom(leftType);
                    }

                    break;
                }
                case BinaryOperator.VarPut:
                {
                    if (typeof(AspectConstruct).IsAssignableFrom(leftType))
                    {
                        AspectConstruct lhs;
                        ExpressionContainerConstruct expressionContainerConstruct;
                        ValueConstruct valueConstruct;

                        rightObj = onDemandRightExpressionEvaluator();

                        rightType = (object)rightObj != null ? rightObj.GetType() : null;

                        lhs = leftObj.ChangeType<AspectConstruct>();

                        expressionContainerConstruct = new ExpressionContainerConstruct();

                        valueConstruct = new ValueConstruct()
                                         {
                                             Type = (object)rightType != null ? rightType.FullName : null,
                                             __ = rightObj
                                         };

                        expressionContainerConstruct.Content = valueConstruct;

                        this.Assign(lhs.Name, expressionContainerConstruct, templatingContext);

                        return rightObj;
                    }

                    break;
                }
                default:
                {
                    throw new InvalidOperationException("TODO (enhancement): add meaningful message | binary operator is not recognized");
                }
            }

            throw new InvalidOperationException("TODO (enhancement): add meaningful message | type is not supported by the binary operator");
        }