diff --git a/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.cpp b/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.cpp index b88ef3d473..61a31cb3bb 100644 --- a/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.cpp +++ b/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.cpp @@ -364,5 +364,62 @@ bdld::Datum SimpleEvaluator::Not::evaluate(EvaluationContext& context) const return bdld::Datum::createBoolean(!value.theBoolean()); } +// --------------------------------- +// class SimpleEvaluator::Abs +// --------------------------------- + +bdld::Datum SimpleEvaluator::Abs::evaluate(EvaluationContext& context) const +{ + bdld::Datum expr = d_expression->evaluate(context); + if (context.d_stop) { + return bdld::Datum::createNull(); // RETURN + } + + bsls::Types::Int64 value; + if (expr.isInteger64()) { + value = expr.theInteger64(); + } + + else if (expr.isInteger()) { + value = expr.theInteger(); + } + else { + context.d_lastError = ErrorType::e_TYPE; + return context.stop(); // RETURN + } + + value = abs(value); + return bdld::Datum::createInteger64(value, context.d_allocator); +} + +// -------------------------- +// class SimpleEvaluator::Exists +// -------------------------- + +SimpleEvaluator::Exists::Exists(const bsl::string& name) +: d_name(name) +{ +} + +#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \ + defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT) +SimpleEvaluator::Exists::Exists(bsl::string&& name) noexcept +: d_name(bsl::move(name)) +{ +} +#endif + +bdld::Datum SimpleEvaluator::Exists::evaluate(EvaluationContext& context) const +{ + bdld::Datum value = context.d_propertiesReader->get(d_name, + context.d_allocator); + + if (value.isError()) { + return bdld::Datum::createBoolean(false); + } + + return bdld::Datum::createBoolean(true); +} + } // close package namespace } // close enterprise namespace diff --git a/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.h b/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.h index 79e4122ba1..0cbd51c86d 100644 --- a/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.h +++ b/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.h @@ -451,6 +451,33 @@ class SimpleEvaluator { evaluate(EvaluationContext& context) const BSLS_KEYWORD_OVERRIDE; }; + // ---------- + // Abs + // ---------- + + class Abs : public Expression { + private: + // DATA + + // The expression to negate. + ExpressionPtr d_expression; + + public: + // CREATORS + + /// Create an object that implements arithmetic negation. + explicit Abs(ExpressionPtr expression); + + // ACCESSORS + + /// Evaluate `expression` passed to the constructor. If it is an + /// integer, return the negated value as an Int64 Datum. Otherwise, + /// set the error in the context to e_TYPE, stop the evaluation, + /// and return a null datum. + bdld::Datum + evaluate(EvaluationContext& context) const BSLS_KEYWORD_OVERRIDE; + }; + // --- // Not // --- @@ -478,6 +505,41 @@ class SimpleEvaluator { evaluate(EvaluationContext& context) const BSLS_KEYWORD_OVERRIDE; }; + // --- + // Exists + // --- + + class Exists : public Expression { + private: + // DATA + + // The name of the property. + bsl::string d_name; + + public: + // CREATORS + + /// Create an object that evaluates property `name`, in the + /// evaluation context, as a boolean. + explicit Exists(const bsl::string& name); + +#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \ + defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT) + /// Create an object that evaluates property `name`, in the + /// evaluation context, as a boolean. + explicit Exists(bsl::string&& name) noexcept; +#endif + + // ACCESSORS + + /// Evaluate `expression` passed to the constructor. If it is a + /// boolean, return the negated value as a boolean Datum. + /// Otherwise, set the error in the context to e_TYPE, stop the + /// evaluation, and return a null datum. + bdld::Datum + evaluate(EvaluationContext& context) const BSLS_KEYWORD_OVERRIDE; + }; + private: // SimpleEvaluator(const SimpleEvaluator& other) BSLS_KEYWORD_DELETED; // SimpleEvaluator& operator=(const SimpleEvaluator& other) @@ -549,6 +611,7 @@ class SimpleEvaluator { friend class SimpleEvaluatorScanner; // for access to Expression hierarchy friend class CompilationContext; // for access to ExpressionPtr }; + // ======================== // class CompilationContext // ======================== @@ -959,6 +1022,15 @@ inline SimpleEvaluator::Not::Not(ExpressionPtr expression) { } +// ------------------------------------------ +// template class SimpleEvaluator::Abs +// ------------------------------------------ + +inline SimpleEvaluator::Abs::Abs(ExpressionPtr expression) +: d_expression(expression) +{ +} + // ------------------------ // class CompilationContext // ------------------------ diff --git a/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.t.cpp b/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.t.cpp index de3fd963fc..64e31a1646 100644 --- a/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.t.cpp +++ b/src/groups/bmq/bmqeval/bmqeval_simpleevaluator.t.cpp @@ -53,8 +53,10 @@ class MockPropertiesReader : public PropertiesReader { d_map["i_2"] = bdld::Datum::createInteger(2); d_map["i_3"] = bdld::Datum::createInteger(3); d_map["i_42"] = bdld::Datum::createInteger(42); + d_map["i_n42"] = bdld::Datum::createInteger(-42); d_map["i64_42"] = bdld::Datum::createInteger64(42, allocator); d_map["s_foo"] = bdld::Datum::createStringRef("foo", allocator); + d_map["exists"] = bdld::Datum::createInteger(42); } // Destroy this object. @@ -427,6 +429,13 @@ static void test3_evaluation() // mixed integer types {"i_42 == 42", true}, + // abs function + {"i_n42 == -42", true}, + {"-i_n42 == 42", true}, + {"abs(i_n42) == 42", true}, + {"abs(i_n42) == i_42", true}, + {"abs(i_42) == i_42", true}, + // string comparisons {"s_foo == \"foo\"", true}, {"s_foo != \"foo\"", false}, @@ -520,6 +529,14 @@ static void test3_evaluation() {"i_0 != -9223372036854775807", true}, // -(2 ** 63) + 1 {"i_0 != 9223372036854775807", true}, // 2 ** 63 - 1 {"i_0 != -9223372036854775808", true}, // -(2 ** 63) + + // exists + {"exists(i_42)", true}, + {"exists(non_existing_property)", false}, + {"exists(i_42) && i_42 > 41", true}, + {"exists(non_existing_property) && non_existing_property > 41", false}, + {"exists == 42", true}, + {"exists(exists)", true}, }; const TestParameters* testParametersEnd = testParameters + sizeof(testParameters) / diff --git a/src/groups/bmq/bmqeval/bmqeval_simpleevaluatorparser.y b/src/groups/bmq/bmqeval/bmqeval_simpleevaluatorparser.y index cfcd81e15e..eed1ade2d0 100644 --- a/src/groups/bmq/bmqeval/bmqeval_simpleevaluatorparser.y +++ b/src/groups/bmq/bmqeval/bmqeval_simpleevaluatorparser.y @@ -75,6 +75,8 @@ %token PLUS "+" MINUS "-"; %token TIMES "*" DIVIDES "/" MODULUS "%"; %token EQ "=" NE "<>" LT "<" LE "<=" GE ">=" GT ">"; +%token EXISTS "exists"; +%token ABS "abs"; %left OR; %left AND; @@ -84,6 +86,7 @@ %left TIMES DIVIDES MODULUS; %right NOT "!"; +%type variable; %type expression; %type predicate; %start predicate @@ -95,18 +98,40 @@ predicate : expression END ctx.d_expression = $1; } -expression +variable : PROPERTY { + ++ctx.d_numProperties; + $$ = $1; + } + | EXISTS + { + ++ctx.d_numProperties; + $$ = $1; + } + | ABS + { + ++ctx.d_numProperties; + $$ = $1; + } -#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) \ +expression + : variable { + #if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) \ && defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT) $$ = ctx.makeUnaryExpression(bsl::move($1)); #else $$ = ctx.makeUnaryExpression($1); #endif - - ++ctx.d_numProperties; + } + | EXISTS LPAR variable RPAR + { +#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) \ +&& defined(BSLS_COMPILERFEATURES_SUPPORT_NOEXCEPT) + $$ = ctx.makeUnaryExpression(bsl::move($3)); +#else + $$ = ctx.makeUnaryExpression($3); +#endif } | INTEGER { $$ = ctx.makeLiteral($1); } @@ -139,6 +164,8 @@ expression { $$ = ctx.makeBooleanBinaryExpression($1, $3); } | NOT expression { $$ = ctx.makeUnaryExpression($2); } + | ABS LPAR expression RPAR + { $$ = ctx.makeUnaryExpression($3); } | expression PLUS expression { $$ = ctx.makeNumBinaryExpression($1, $3); } | expression MINUS expression diff --git a/src/groups/bmq/bmqeval/bmqeval_simpleevaluatorscanner.l b/src/groups/bmq/bmqeval/bmqeval_simpleevaluatorscanner.l index c0da8dea85..51f6de212d 100644 --- a/src/groups/bmq/bmqeval/bmqeval_simpleevaluatorscanner.l +++ b/src/groups/bmq/bmqeval/bmqeval_simpleevaluatorscanner.l @@ -32,6 +32,16 @@ return SimpleEvaluatorParser::make_FALSE(); } +"exists" { + updatePosition(); + return SimpleEvaluatorParser::make_EXISTS(yytext); +} + +"abs" { + updatePosition(); + return SimpleEvaluatorParser::make_ABS(yytext); +} + [a-zA-Z][a-zA-Z0-9_.]* { updatePosition(); return SimpleEvaluatorParser::make_PROPERTY(yytext); diff --git a/src/groups/bmq/bmqu/bmqu_operationchain.h b/src/groups/bmq/bmqu/bmqu_operationchain.h index 01465b8246..2633ad1a79 100644 --- a/src/groups/bmq/bmqu/bmqu_operationchain.h +++ b/src/groups/bmq/bmqu/bmqu_operationchain.h @@ -192,7 +192,7 @@ #if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // Include version that can be compiled with C++03 -// Generated on Tue Oct 15 17:39:53 2024 +// Generated on Fri Feb 14 17:43:15 2025 // Command line: sim_cpp11_features.pl bmqu_operationchain.h #define COMPILING_BMQU_OPERATIONCHAIN_H #include diff --git a/src/groups/bmq/bmqu/bmqu_operationchain_cpp03.h b/src/groups/bmq/bmqu/bmqu_operationchain_cpp03.h index dd69f868df..7ba56d53cd 100644 --- a/src/groups/bmq/bmqu/bmqu_operationchain_cpp03.h +++ b/src/groups/bmq/bmqu/bmqu_operationchain_cpp03.h @@ -36,7 +36,7 @@ // regions of C++11 code, then this header contains no code and is not // '#include'd in the original header. // -// Generated on Thu Oct 17 16:05:19 2024 +// Generated on Fri Feb 14 17:43:15 2025 // Command line: sim_cpp11_features.pl bmqu_operationchain.h #ifdef COMPILING_BMQU_OPERATIONCHAIN_H @@ -1288,6 +1288,3 @@ inline void bmqu::swap(OperationChainLink& lhs, #endif // ! defined(COMPILING_BMQU_OPERATIONCHAIN_H) #endif // ! defined(INCLUDED_BMQU_OPERATIONCHAIN_CPP03) - -// SCRIPT-SHA: 60926cad35f1091c31a7d8cc9d33acc38edd25e4891f3e1d41fe7c40fd6e02f5 -// SOURCE-SHA: 7610aa7a0ecb116c786702dfc71b197eda2f52aa0f3efa66433723466764a626