00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "AtomicValue.h"
00016 #include "Boolean.h"
00017 #include "BuiltinTypes.h"
00018 #include "CommonSequenceTypes.h"
00019 #include "CommonValues.h"
00020 #include "OptimizationPasses.h"
00021
00022 #include "ValueComparison.h"
00023
00024 using namespace Patternist;
00025
00026 ValueComparison::ValueComparison(const Expression::Ptr &op1,
00027 const AtomicComparator::Operator op,
00028 const Expression::Ptr &op2) : PairContainer(op1, op2),
00029 m_operator(op)
00030 {
00031 }
00032
00033 Item::Ptr ValueComparison::evaluateSingleton(const DynamicContext::Ptr &context) const
00034 {
00035 const Item::Ptr it1(m_operand1->evaluateSingleton(context));
00036 if(!it1)
00037 return Item::Ptr();
00038
00039 const Item::Ptr it2(m_operand2->evaluateSingleton(context));
00040 if(!it2)
00041 return Item::Ptr();
00042
00043 return Boolean::fromValue(flexibleCompare(it1, it2, context));
00044 }
00045
00046 Expression::Ptr ValueComparison::typeCheck(const StaticContext::Ptr &context,
00047 const SequenceType::Ptr &reqType)
00048 {
00049 const Expression::Ptr me(PairContainer::typeCheck(context, reqType));
00050 const ItemType::Ptr t1(m_operand1->staticType()->itemType());
00051 const ItemType::Ptr t2(m_operand2->staticType()->itemType());
00052 Q_ASSERT(t1);
00053 Q_ASSERT(t2);
00054
00055 if(*CommonSequenceTypes::Empty == *t1 ||
00056 *CommonSequenceTypes::Empty == *t2)
00057 {
00058 return CommonValues::emptySequence;
00059 }
00060 else
00061 {
00062 prepareComparison(fetchComparator(t1, t2, context));
00063
00064 return me;
00065 }
00066 }
00067
00068 Expression::Ptr ValueComparison::compress(const StaticContext::Ptr &context)
00069 {
00070 const Expression::Ptr me(PairContainer::compress(context));
00071
00072 if(me.get() != this)
00073 return me;
00074
00075 if(isCaseInsensitiveCompare(m_operand1, m_operand2))
00076 useCaseInsensitiveComparator();
00077
00078 return me;
00079 }
00080
00081 bool ValueComparison::isCaseInsensitiveCompare(Expression::Ptr &op1, Expression::Ptr &op2)
00082 {
00083 Q_ASSERT(op1);
00084 Q_ASSERT(op2);
00085
00086 const ID iD = op1->id();
00087
00088 if((iD == IDLowerCaseFN || iD == IDUpperCaseFN) && iD == op2->id())
00089 {
00090
00091
00092
00093 op1 = op1->operands().first();
00094 op2 = op2->operands().first();
00095
00096 return true;
00097 }
00098 else
00099 return false;
00100 }
00101
00102 OptimizationPass::List ValueComparison::optimizationPasses() const
00103 {
00104 return OptimizationPasses::comparisonPasses;
00105 }
00106
00107 SequenceType::List ValueComparison::expectedOperandTypes() const
00108 {
00109 SequenceType::List result;
00110 result.append(CommonSequenceTypes::ZeroOrOneAtomicType);
00111 result.append(CommonSequenceTypes::ZeroOrOneAtomicType);
00112 return result;
00113 }
00114
00115 SequenceType::Ptr ValueComparison::staticType() const
00116 {
00117 if(m_operand1->staticType()->cardinality().allowsEmpty() ||
00118 m_operand2->staticType()->cardinality().allowsEmpty())
00119 return CommonSequenceTypes::ZeroOrOneBoolean;
00120 else
00121 return CommonSequenceTypes::ExactlyOneBoolean;
00122 }
00123
00124 ExpressionVisitorResult::Ptr ValueComparison::accept(const ExpressionVisitor::Ptr &visitor) const
00125 {
00126 return visitor->visit(this);
00127 }
00128
00129 Expression::ID ValueComparison::id() const
00130 {
00131 return IDValueComparison;
00132 }
00133
00134