protected function evaluate($exp)
    {
        list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp;

        $left = $this->reduce($left);
        $right = $this->reduce($right);

        if ($leftColor = $this->coerceColor($left)) {
            $left = $leftColor;
        }

        if ($rightColor = $this->coerceColor($right)) {
            $right = $rightColor;
        }

        $ltype = $left[0];
        $rtype = $right[0];

        // operators that work on all types
        if ($op == 'and') {
            return $this->toBool($left == self::$TRUE && $right == self::$TRUE);
        }

        if ($op == '=') {
            return $this->toBool($this->eq($left, $right));
        }

        if ($op == '+' && !is_null($str = $this->stringConcatenate($left, $right))) {
            return $str;
        }

        // type based operators
        $fname = "op_${ltype}_${rtype}";
        if (is_callable(array($this, $fname))) {
            $out = $this->$fname($op, $left, $right);
            if (!is_null($out)) {
                return $out;
            }
        }

        // make the expression look it did before being parsed
        $paddedOp = $op;
        if ($whiteBefore) {
            $paddedOp = ' '.$paddedOp;
        }
        if ($whiteAfter) {
            $paddedOp .= ' ';
        }

        return array('string', '', array($left, $paddedOp, $right));
    }
protected function evaluate($exp)
    {
        list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp;

        $left = $this->reduce($left);
        $right = $this->reduce($right);

        if ($leftColor = $this->coerceColor($left)) {
            $left = $leftColor;
        }

        if ($rightColor = $this->coerceColor($right)) {
            $right = $rightColor;
        }

        $ltype = $left[0];
        $rtype = $right[0];

        // operators that work on all types
        if ($op == 'and') {
            return $this->toBool($left == self::$TRUE && $right == self::$TRUE);
        }

        if ($op == '=') {
            return $this->toBool($this->eq($left, $right));
        }

        if ($op == '+' && !is_null($str = $this->stringConcatenate($left, $right))) {
            return $str;
        }

        // type based operators
        $fname = "op_${ltype}_${rtype}";
        if (is_callable(array($this, $fname))) {
            $out = $this->$fname($op, $left, $right);
            if (!is_null($out)) {
                return $out;
            }
        }

        // make the expression look it did before being parsed
        $paddedOp = $op;
        if ($whiteBefore) {
            $paddedOp = ' '.$paddedOp;
        }
        if ($whiteAfter) {
            $paddedOp .= ' ';
        }

        return array('string', '', array($left, $paddedOp, $right));
    }
protected function evaluate ( $ exp ) { list ( , $ op , $ left , $ right , $ whiteBefore , $ whiteAfter ) = $ exp ; $ left = $ this -> reduce ( $ left ) ; $ right = $ this -> reduce ( $ right ) ; if ( $ leftColor = $ this -> coerceColor ( $ left ) ) { $ left = $ leftColor ; } if ( $ rightColor = $ this -> coerceColor ( $ right ) ) { $ right = $ rightColor ; } $ ltype = $ left [ 0 ] ; $ rtype = $ right [ 0 ] ; // operators that work on all types if ( $ op == 'and' ) { return $ this -> toBool ( $ left == self :: $ TRUE && $ right == self :: $ TRUE ) ; } if ( $ op == '=' ) { return $ this -> toBool ( $ this -> eq ( $ left , $ right ) ) ; } if ( $ op == '+' && ! is_null ( $ str = $ this -> stringConcatenate ( $ left , $ right ) ) ) { return $ str ; } // type based operators $ fname = "op_${ltype}_${rtype}" ; if ( is_callable ( array ( $ this , $ fname ) ) ) { $ out = $ this -> $ fname ( $ op , $ left , $ right ) ; if ( ! is_null ( $ out ) ) { return $ out ; } } // make the expression look it did before being parsed $ paddedOp = $ op ; if ( $ whiteBefore ) { $ paddedOp = ' ' . $ paddedOp ; } if ( $ whiteAfter ) { $ paddedOp .= ' ' ; } return array ( 'string' , '' , array ( $ left , $ paddedOp , $ right ) ) ; }
evaluate an expression
evaluate an expression