Skip to content

Commit f3ba418

Browse files
bbpetukhov678098
andauthored
Feat[bmq]: support exists(x) function in subscription expressions (#594)
* Implement support for exists() in BISON expressions Signed-off-by: Dmitrii Petukhov <[email protected]> * Update src/groups/bmq/bmqeval/bmqeval_simpleevaluator.cpp Co-authored-by: Evgeny Malygin <[email protected]> Signed-off-by: Dmitrii Petukhov <[email protected]> * Update src/groups/bmq/bmqeval/bmqeval_simpleevaluator.h Co-authored-by: Evgeny Malygin <[email protected]> Signed-off-by: Dmitrii Petukhov <[email protected]> * Update src/groups/bmq/bmqeval/bmqeval_simpleevaluator.h Co-authored-by: Evgeny Malygin <[email protected]> Signed-off-by: Dmitrii Petukhov <[email protected]> * Update src/groups/bmq/bmqeval/bmqeval_simpleevaluator.t.cpp Co-authored-by: Evgeny Malygin <[email protected]> Signed-off-by: Dmitrii Petukhov <[email protected]> * Update src/groups/bmq/bmqeval/bmqeval_simpleevaluator.t.cpp Co-authored-by: Evgeny Malygin <[email protected]> Signed-off-by: Dmitrii Petukhov <[email protected]> * Refactor Exists::evaluate - make code smpler Signed-off-by: Dmitrii Petukhov <[email protected]> --------- Signed-off-by: Dmitrii Petukhov <[email protected]> Co-authored-by: Evgeny Malygin <[email protected]>
1 parent b6dfeae commit f3ba418

5 files changed

+102
-4
lines changed

src/groups/bmq/bmqeval/bmqeval_simpleevaluator.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -364,5 +364,30 @@ bdld::Datum SimpleEvaluator::Not::evaluate(EvaluationContext& context) const
364364
return bdld::Datum::createBoolean(!value.theBoolean());
365365
}
366366

367+
// -----------------------------
368+
// class SimpleEvaluator::Exists
369+
// -----------------------------
370+
371+
SimpleEvaluator::Exists::Exists(const bsl::string& name)
372+
: d_name(name)
373+
{
374+
}
375+
376+
#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
377+
defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT)
378+
SimpleEvaluator::Exists::Exists(bsl::string&& name) noexcept
379+
: d_name(bsl::move(name))
380+
{
381+
}
382+
#endif
383+
384+
bdld::Datum SimpleEvaluator::Exists::evaluate(EvaluationContext& context) const
385+
{
386+
bdld::Datum value = context.d_propertiesReader->get(d_name,
387+
context.d_allocator);
388+
389+
return bdld::Datum::createBoolean(!value.isError());
390+
}
391+
367392
} // close package namespace
368393
} // close enterprise namespace

src/groups/bmq/bmqeval/bmqeval_simpleevaluator.h

+36
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,41 @@ class SimpleEvaluator {
478478
evaluate(EvaluationContext& context) const BSLS_KEYWORD_OVERRIDE;
479479
};
480480

481+
// ------
482+
// Exists
483+
// ------
484+
485+
class Exists : public Expression {
486+
private:
487+
// DATA
488+
489+
// The name of the property.
490+
bsl::string d_name;
491+
492+
public:
493+
// CREATORS
494+
495+
/// Create an object that evaluates property `name`, in the
496+
/// evaluation context, as a boolean.
497+
explicit Exists(const bsl::string& name);
498+
499+
#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
500+
defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT)
501+
/// Create an object that evaluates property `name`, in the
502+
/// evaluation context, as a boolean.
503+
explicit Exists(bsl::string&& name) noexcept;
504+
#endif
505+
506+
// ACCESSORS
507+
508+
/// Evaluate `expression` passed to the constructor. If it is a
509+
/// boolean, return the negated value as a boolean Datum.
510+
/// Otherwise, set the error in the context to e_TYPE, stop the
511+
/// evaluation, and return a null datum.
512+
bdld::Datum
513+
evaluate(EvaluationContext& context) const BSLS_KEYWORD_OVERRIDE;
514+
};
515+
481516
private:
482517
// SimpleEvaluator(const SimpleEvaluator& other) BSLS_KEYWORD_DELETED;
483518
// SimpleEvaluator& operator=(const SimpleEvaluator& other)
@@ -549,6 +584,7 @@ class SimpleEvaluator {
549584
friend class SimpleEvaluatorScanner; // for access to Expression hierarchy
550585
friend class CompilationContext; // for access to ExpressionPtr
551586
};
587+
552588
// ========================
553589
// class CompilationContext
554590
// ========================

src/groups/bmq/bmqeval/bmqeval_simpleevaluator.t.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class MockPropertiesReader : public PropertiesReader {
5555
d_map["i_42"] = bdld::Datum::createInteger(42);
5656
d_map["i64_42"] = bdld::Datum::createInteger64(42, allocator);
5757
d_map["s_foo"] = bdld::Datum::createStringRef("foo", allocator);
58+
d_map["exists"] = bdld::Datum::createInteger(42);
5859
}
5960
// Destroy this object.
6061

@@ -520,6 +521,18 @@ static void test3_evaluation()
520521
{"i_0 != -9223372036854775807", true}, // -(2 ** 63) + 1
521522
{"i_0 != 9223372036854775807", true}, // 2 ** 63 - 1
522523
{"i_0 != -9223372036854775808", true}, // -(2 ** 63)
524+
525+
// exists
526+
// Note that we allow to set a message property with name `exists`.
527+
// In this case the usage context defines whether it's a function call
528+
// or a property value.
529+
{"exists(i_42)", true},
530+
{"exists(non_existing_property)", false},
531+
{"!exists(non_existing_property) || non_existing_property > 41", true},
532+
{"exists(i_42) && i_42 > 41", true},
533+
{"exists(non_existing_property) && non_existing_property > 41", false},
534+
{"exists == 42", true},
535+
{"exists(exists)", true},
523536
};
524537
const TestParameters* testParametersEnd = testParameters +
525538
sizeof(testParameters) /

src/groups/bmq/bmqeval/bmqeval_simpleevaluatorparser.y

+23-4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
%token PLUS "+" MINUS "-";
7676
%token TIMES "*" DIVIDES "/" MODULUS "%";
7777
%token EQ "=" NE "<>" LT "<" LE "<=" GE ">=" GT ">";
78+
%token <bsl::string> EXISTS "exists";
7879

7980
%left OR;
8081
%left AND;
@@ -84,6 +85,7 @@
8485
%left TIMES DIVIDES MODULUS;
8586
%right NOT "!";
8687

88+
%type<bsl::string> variable;
8789
%type<SimpleEvaluator::ExpressionPtr> expression;
8890
%type<SimpleEvaluator::ExpressionPtr> predicate;
8991
%start predicate
@@ -95,18 +97,35 @@ predicate : expression END
9597
ctx.d_expression = $1;
9698
}
9799

98-
expression
100+
variable
99101
: PROPERTY
100102
{
103+
++ctx.d_numProperties;
104+
$$ = $1;
105+
}
106+
| EXISTS
107+
{
108+
++ctx.d_numProperties;
109+
$$ = $1;
110+
}
101111

102-
#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) \
112+
expression
113+
: variable {
114+
#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) \
103115
&& defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT)
104116
$$ = ctx.makeUnaryExpression<SimpleEvaluator::Property, bsl::string>(bsl::move($1));
105117
#else
106118
$$ = ctx.makeUnaryExpression<SimpleEvaluator::Property, bsl::string>($1);
107119
#endif
108-
109-
++ctx.d_numProperties;
120+
}
121+
| EXISTS LPAR variable RPAR
122+
{
123+
#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) \
124+
&& defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT)
125+
$$ = ctx.makeUnaryExpression<SimpleEvaluator::Exists, bsl::string>(bsl::move($3));
126+
#else
127+
$$ = ctx.makeUnaryExpression<SimpleEvaluator::Exists, bsl::string>($3);
128+
#endif
110129
}
111130
| INTEGER
112131
{ $$ = ctx.makeLiteral<SimpleEvaluator::IntegerLiteral>($1); }

src/groups/bmq/bmqeval/bmqeval_simpleevaluatorscanner.l

+5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
return SimpleEvaluatorParser::make_FALSE();
3333
}
3434

35+
"exists" {
36+
updatePosition();
37+
return SimpleEvaluatorParser::make_EXISTS(yytext);
38+
}
39+
3540
[a-zA-Z][a-zA-Z0-9_.]* {
3641
updatePosition();
3742
return SimpleEvaluatorParser::make_PROPERTY(yytext);

0 commit comments

Comments
 (0)