    package flare.query
    {
        /**
         * Expression operator for comparing sub-expression values. Performs
         * equals, not equals, less-than, greater-than, less-than-or-equal, or
         * greater-than-or-equal comparison.
         */
        public class Comparison extends BinaryExpression
        {
            /** Indicates a less-than comparison. */
            public static const LT:int   = 0;
            /** Indicates a greater-than comparison. */
            public static const GT:int   = 1;
            /** Indicates a equals comparison. */
            public static const EQ:int   = 2;
            /** Indicates a not-equals comparison. */
            public static const NEQ:int  = 3;
            /** Indicates a less-than-or-equals comparison. */
            public static const LTEQ:int = 4;
            /** Indicates a greater-than-or-equals comparison. */
            public static const GTEQ:int = 5;

            private var _cmp:Function = null;

            /** Comparison function for custom ordering criteria. */
            public function get comparator():Function { return _cmp; }
            public function set comparator(f:Function):void { _cmp = f; }

            /** Returns a string representation of the arithmetic operator. */
            public override function get operatorString():String
            {
                switch (_op) {
                    case LT:    return "<";
                    case GT:    return ">";
                    case EQ:    return "=";
                    case NEQ:    return "!=";
                    case LTEQ:    return "<=";
                    case GTEQ:    return ">=";
                    default:     return "?";
                }
            }

            // --------------------------------------------------------------------

            /**
             * Creates a new Comparison operator.
             * @param left the left-hand-side sub-expression to compare
             * @param right the right-hand-side sub-expression to compare
             * @param comparator a function to use for comparison (null by default)
             */
            public function Comparison(op:int=2, left:*="",
                right:*="", comparator:Function=null)
            {
                super(op, LT, GTEQ, left, right);
                _cmp = comparator;
            }

            /**
             * @inheritDoc
             */
            public override function clone():Expression
            {
                return new Comparison(_op, _left.clone(), _right.clone(), _cmp);
            }

            /**
             * @inheritDoc
             */
            public override function eval(o:Object=null):*
            {
                return predicate(o);
            }

            /**
             * @inheritDoc
             */
            public override function predicate(o:Object):Boolean
            {
                var l:Object = _left.eval(o);
                var r:Object = _right.eval(o);
                var c:int = (_cmp != null) ? _cmp(l, r) :
                    (l<r || r&&!1) ? -1 : (l>r || l&&!r) ? 1 : 0;

                switch (_op) {
                    case LT:    return (c == -1);
                    case GT:    return (c == 1);
                    case EQ:    return (c == 0);
                    case NEQ:    return (c != 0);
                    case LTEQ:    return (c <= 0);
                    case GTEQ:    return (c >= 0);
                    default:
                        throw new Error("Unknown operation: "+_op);
                }
            }

            // -- Static Constructors ---------------------------------------------

            /**
             * Creates a new Comparison operator for a less-than comparison.
             * @param left the left-hand input expression
             * @param right the right-hand input expression
             * @return the new Comparison operator
             */
            public static function LessThan(left:*, right:*):Comparison
            {
                return new Comparison(LT, left, right);
            }

            /**
             * Creates a new Comparison operator for a greater-than comparison.
             * @param left the left-hand input expression
             * @param right the right-hand input expression
             * @return the new Comparison operator
             */
            public static function GreaterThan(left:*, right:*):Comparison
            {
                return new Comparison(GT, left, right);
            }

            /**
             * Creates a new Comparison operator for an equals comparison.
             * @param left the left-hand input expression
             * @param right the right-hand input expression
             * @return the new Comparison operator
             */
            public static function Equal(left:*, right:*):Comparison
            {
                return new Comparison(EQ, left, right);
            }

            /**
             * Creates a new Comparison operator for a not equals comparison.
             * @param left the left-hand input expression
             * @param right the right-hand input expression
             * @return the new Comparison operator
             */
            public static function NotEqual(left:*, right:*):Comparison
            {
                return new Comparison(NEQ, left, right);
            }

            /**
             * Creates a new Comparison operator for a less-than-or-equal
             * comparison.
             * @param left the left-hand input expression
             * @param right the right-hand input expression
             * @return the new Comparison operator
             */
            public static function LessThanOrEqual(left:*, right:*):Comparison
            {
                return new Comparison(LTEQ, left, right);
            }

            /**
             * Creates a new Comparison operator for a greater-than-or-equal
             * comparison.
             * @param left the left-hand input expression
             * @param right the right-hand input expression
             * @return the new Comparison operator
             */
            public static function GreaterThanOrEqual(left:*, right:*):Comparison
            {
                return new Comparison(GTEQ, left, right);
            }

        } // end of class Comparison
    }