Skip to content

Commit 3dd4609

Browse files
authored
Implement 'in' tester
* Begin implementing testers * Test for 'gt', 'ge', 'lt' and 'le' testers * Implement 'defined' and 'undefined' testers * Fix build * Implement 'iterable', 'mapping', 'number', 'sequence' and 'string' testers * Implement 'in' tester
1 parent b1d38c7 commit 3dd4609

File tree

4 files changed

+75
-29
lines changed

4 files changed

+75
-29
lines changed

src/expression_evaluator.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,23 @@ InternalValue UnaryExpression::Evaluate(RenderContext& values)
4747
return Apply<visitors::UnaryOperation>(m_expr->Evaluate(values), m_oper);
4848
}
4949

50+
BinaryExpression::BinaryExpression(BinaryExpression::Operation oper, ExpressionEvaluatorPtr<> leftExpr, ExpressionEvaluatorPtr<> rightExpr)
51+
: m_oper(oper)
52+
, m_leftExpr(leftExpr)
53+
, m_rightExpr(rightExpr)
54+
{
55+
if (m_oper == In)
56+
{
57+
CallParams params;
58+
params.kwParams["seq"] = rightExpr;
59+
m_inTester = CreateTester("in", params);
60+
}
61+
}
62+
5063
InternalValue BinaryExpression::Evaluate(RenderContext& context)
5164
{
5265
InternalValue leftVal = m_leftExpr->Evaluate(context);
53-
InternalValue rightVal = m_rightExpr->Evaluate(context);
66+
InternalValue rightVal = m_oper == In ? InternalValue() : m_rightExpr->Evaluate(context);
5467
InternalValue result;
5568

5669
switch (m_oper)
@@ -64,7 +77,6 @@ InternalValue BinaryExpression::Evaluate(RenderContext& context)
6477
case jinja2::BinaryExpression::LogicalLt:
6578
case jinja2::BinaryExpression::LogicalGe:
6679
case jinja2::BinaryExpression::LogicalLe:
67-
case jinja2::BinaryExpression::In:
6880
case jinja2::BinaryExpression::Plus:
6981
case jinja2::BinaryExpression::Minus:
7082
case jinja2::BinaryExpression::Mul:
@@ -74,6 +86,11 @@ InternalValue BinaryExpression::Evaluate(RenderContext& context)
7486
case jinja2::BinaryExpression::Pow:
7587
result = Apply2<visitors::BinaryMathOperation>(leftVal, rightVal, m_oper);
7688
break;
89+
case jinja2::BinaryExpression::In:
90+
{
91+
result = m_inTester->Test(leftVal, context);
92+
break;
93+
}
7794
case jinja2::BinaryExpression::StringConcat:
7895
default:
7996
break;

src/expression_evaluator.h

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,27 @@ class UnaryExpression : public Expression
185185
ExpressionEvaluatorPtr<> m_expr;
186186
};
187187

188+
class IsExpression : public Expression
189+
{
190+
public:
191+
virtual ~IsExpression() {}
192+
193+
struct ITester
194+
{
195+
virtual ~ITester() {}
196+
virtual bool Test(const InternalValue& baseVal, RenderContext& context) = 0;
197+
};
198+
199+
using TesterFactoryFn = std::function<std::shared_ptr<ITester> (CallParams params)>;
200+
201+
IsExpression(ExpressionEvaluatorPtr<> value, std::string tester, CallParams params);
202+
InternalValue Evaluate(RenderContext& context) override;
203+
204+
private:
205+
ExpressionEvaluatorPtr<> m_value;
206+
std::shared_ptr<ITester> m_tester;
207+
};
208+
188209
class BinaryExpression : public Expression
189210
{
190211
public:
@@ -216,38 +237,15 @@ class BinaryExpression : public Expression
216237
CaseInsensitive = 1
217238
};
218239

219-
BinaryExpression(Operation oper, ExpressionEvaluatorPtr<> leftExpr, ExpressionEvaluatorPtr<> rightExpr)
220-
: m_oper(oper)
221-
, m_leftExpr(leftExpr)
222-
, m_rightExpr(rightExpr)
223-
{}
240+
BinaryExpression(Operation oper, ExpressionEvaluatorPtr<> leftExpr, ExpressionEvaluatorPtr<> rightExpr);
224241
InternalValue Evaluate(RenderContext&) override;
225242
private:
226243
Operation m_oper;
227244
ExpressionEvaluatorPtr<> m_leftExpr;
228245
ExpressionEvaluatorPtr<> m_rightExpr;
246+
std::shared_ptr<IsExpression::ITester> m_inTester;
229247
};
230248

231-
class IsExpression : public Expression
232-
{
233-
public:
234-
virtual ~IsExpression() {}
235-
236-
struct ITester
237-
{
238-
virtual ~ITester() {}
239-
virtual bool Test(const InternalValue& baseVal, RenderContext& context) = 0;
240-
};
241-
242-
using TesterFactoryFn = std::function<std::shared_ptr<ITester> (CallParams params)>;
243-
244-
IsExpression(ExpressionEvaluatorPtr<> value, std::string tester, CallParams params);
245-
InternalValue Evaluate(RenderContext& context) override;
246-
247-
private:
248-
ExpressionEvaluatorPtr<> m_value;
249-
std::shared_ptr<ITester> m_tester;
250-
};
251249

252250
class CallExpression : public Expression
253251
{

src/testers.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ ValueTester::ValueTester(TesterParams params, ValueTester::Mode mode)
108108
case IsEvenMode:
109109
break;
110110
case IsInMode:
111+
ParseParams({{"seq", true}}, params);
111112
break;
112113
case IsIterableMode:
113114
break;
@@ -212,7 +213,27 @@ bool ValueTester::Test(const InternalValue& baseVal, RenderContext& context)
212213
result = valKind == ValueKind::Empty;
213214
break;
214215
case IsInMode:
216+
{
217+
bool isConverted = false;
218+
auto seq = GetArgumentValue("seq", context);
219+
ListAdapter values = ConvertToList(seq, InternalValue(), isConverted);
220+
221+
if (!isConverted)
222+
return false;
223+
224+
auto equalComparator = [&baseVal](auto& val) {
225+
InternalValue cmpRes;
226+
227+
cmpRes = Apply2<visitors::BinaryMathOperation>(val, baseVal, BinaryExpression::LogicalEq);
228+
229+
return ConvertToBool(cmpRes);
230+
};
231+
232+
auto p = std::find_if(values.begin(), values.end(), equalComparator);
233+
result = p != values.end();
234+
215235
break;
236+
}
216237
case IsEvenMode:
217238
break;
218239
case IsOddMode:

test/testers_test.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ INSTANTIATE_TEST_CASE_P(NumberTest, TestersGenericTest, ::testing::Values(
204204
InputOutputPair{"reflectedVal is number", "false"},
205205
InputOutputPair{"reflectedList is number", "false"}
206206
));
207-
207+
208208
INSTANTIATE_TEST_CASE_P(SequenceTest, TestersGenericTest, ::testing::Values(
209209
InputOutputPair{"0 is sequence", "false"},
210210
InputOutputPair{"'intList' is sequence", "false"},
@@ -225,7 +225,7 @@ INSTANTIATE_TEST_CASE_P(SequenceTest, TestersGenericTest, ::testing::Values(
225225
InputOutputPair{"reflectedList is sequence", "true"}
226226
));
227227

228-
228+
229229
INSTANTIATE_TEST_CASE_P(StringTest, TestersGenericTest, ::testing::Values(
230230
InputOutputPair{"0 is string", "false"},
231231
InputOutputPair{"'intList' is string", "true"},
@@ -245,3 +245,13 @@ INSTANTIATE_TEST_CASE_P(StringTest, TestersGenericTest, ::testing::Values(
245245
InputOutputPair{"reflectedVal is string", "false"},
246246
InputOutputPair{"reflectedList is string", "false"}
247247
));
248+
249+
250+
INSTANTIATE_TEST_CASE_P(InTest, TestersGenericTest, ::testing::Values(
251+
InputOutputPair{"0 in (2, 1, 0)", "true"},
252+
InputOutputPair{"0 in (1, 2, 3)", "false"},
253+
InputOutputPair{"0 in intList", "true"},
254+
InputOutputPair{"1000 in intList", "false"},
255+
InputOutputPair{"'string9' in stringList", "true"},
256+
InputOutputPair{"'string90' in stringList", "false"}
257+
));

0 commit comments

Comments
 (0)