28 using expr_ptr = std::shared_ptr<struct ExprBase>;
33 const auto str = value.cast<std::string>();
44 auto it = env.
enums->find(str);
45 if(it != env.
enums->end())
50 return value.cast<
double>();
55 using Ptr = std::shared_ptr<ExprBase>;
61 inline std::string
ErrorNotInit(
const char* side,
const char* op_str)
63 return StrCat(
"The ", side,
" operand of the operator [", op_str,
64 "] is not initialized");
93 if(enum_ptr != env.
enums->end())
95 return Any(
double(enum_ptr->second));
123 auto rhs_v =
rhs->evaluate(env);
126 const double rv = rhs_v.cast<
double>();
132 return Any(
static_cast<double>(~
static_cast<int64_t
>(rv)));
134 return Any(
static_cast<double>(!
static_cast<bool>(rv)));
137 else if(rhs_v.isString())
199 auto lhs_v =
lhs->evaluate(env);
200 auto rhs_v =
rhs->evaluate(env);
211 if(rhs_v.isNumber() && lhs_v.isNumber())
213 auto lv = lhs_v.cast<
double>();
214 auto rv = rhs_v.cast<
double>();
234 int64_t li = lhs_v.cast<int64_t>();
235 int64_t ri = rhs_v.cast<int64_t>();
239 return Any(
static_cast<double>(li & ri));
241 return Any(
static_cast<double>(li | ri));
243 return Any(
static_cast<double>(li ^ ri));
250 throw RuntimeError(
"Binary operators are not allowed if "
251 "one of the operands is not an integer");
259 auto lb = lhs_v.cast<
bool>();
260 auto rb = rhs_v.cast<
bool>();
264 return Any(
static_cast<double>(lb || rb));
266 return Any(
static_cast<double>(lb && rb));
273 throw RuntimeError(
"Logic operators are not allowed if "
274 "one of the operands is not castable to bool");
278 else if(rhs_v.isString() && lhs_v.isString() &&
op ==
plus)
280 return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
282 else if(
op ==
concat && ((rhs_v.isString() && lhs_v.isString()) ||
283 (rhs_v.isString() && lhs_v.isNumber()) ||
284 (rhs_v.isNumber() && lhs_v.isString())))
286 return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
297 template <
typename T>
300 if constexpr(std::is_same_v<double, T>)
302 constexpr
double EPS =
static_cast<double>(std::numeric_limits<float>::epsilon());
303 return std::abs(lv - rv) <= EPS;
348 auto SwitchImpl = [&](
const auto& lv,
const auto& rv,
op_t op) {
379 auto lhs_v =
operands[0]->evaluate(env);
380 for(
auto i = 0u; i !=
ops.size(); ++i)
382 auto rhs_v =
operands[i + 1]->evaluate(env);
392 const Any False(0.0);
394 if(lhs_v.isNumber() && rhs_v.isNumber())
396 auto lv = lhs_v.cast<
double>();
397 auto rv = rhs_v.cast<
double>();
398 if(!SwitchImpl(lv, rv,
ops[i]))
403 else if(lhs_v.isString() && rhs_v.isString())
407 if(!SwitchImpl(lv, rv,
ops[i]))
412 else if(lhs_v.isString() && rhs_v.isNumber())
415 auto rv = rhs_v.cast<
double>();
416 if(!SwitchImpl(lv, rv,
ops[i]))
421 else if(lhs_v.isNumber() && rhs_v.isString())
423 auto lv = lhs_v.
cast<
double>();
425 if(!SwitchImpl(lv, rv,
ops[i]))
453 const auto& v =
condition->evaluate(env);
455 (v.cast<
double>() != 0.0);
458 return then->evaluate(env);
462 return else_->evaluate(env);
510 throw RuntimeError(
"Assignment left operand not a blackboard entry");
512 const auto& key = varname->name;
514 auto entry = env.
vars->getEntry(key);
521 entry = env.
vars->getEntry(key);
530 auto msg =
StrCat(
"The blackboard entry [", key,
531 "] doesn't exist, yet.\n"
532 "If you want to create a new one, "
534 "[:=] instead of [=]");
538 auto value =
rhs->evaluate(env);
540 std::scoped_lock lock(entry->entry_mutex);
541 auto* dst_ptr = &entry->value;
543 auto errorPrefix = [dst_ptr, &key]() {
544 return StrCat(
"Error assigning a value to entry [", key,
"] with type [",
557 if(dst_ptr->empty() && entry->info.type() ==
typeid(
AnyTypeAllowed))
561 else if(value.isString() && !dst_ptr->isString())
565 auto const str = value.cast<std::string>();
566 const auto* entry_info = env.
vars->entryInfo(key);
568 if(
auto converter = entry_info->converter())
570 *dst_ptr = converter(str);
572 else if(dst_ptr->isNumber())
575 *dst_ptr =
Any(num_value);
579 auto msg =
StrCat(errorPrefix(),
580 "\nThe right operand is a string, "
590 value.copyInto(*dst_ptr);
592 catch(std::exception&)
594 auto msg =
StrCat(errorPrefix(),
"\nThe right operand has type [",
595 BT::demangle(value.type()),
"] and can't be converted to [",
600 entry->sequence_id++;
601 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
611 Any temp_variable = *dst_ptr;
617 throw RuntimeError(
"This Assignment operator can't be used "
618 "with a non-numeric type");
621 auto lv = temp_variable.
cast<
double>();
622 auto rv = value.cast<
double>();
626 temp_variable =
Any(lv + rv);
629 temp_variable =
Any(lv - rv);
632 temp_variable =
Any(lv * rv);
635 temp_variable =
Any(lv / rv);
641 else if(value.isString())
645 auto lv = temp_variable.
cast<std::string>();
646 auto rv = value.cast<std::string>();
647 temp_variable =
Any(lv + rv);
651 throw RuntimeError(
"Operator not supported for strings");
656 entry->sequence_id++;
657 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
665 namespace dsl = lexy::dsl;
676 static constexpr
auto rule = dsl::recurse<struct Expression>;
678 static constexpr
auto value = lexy::forward<Ast::expr_ptr>;
688 static constexpr
auto name =
"expected operand";
692 static constexpr
auto atom = [] {
694 auto boolean = dsl::p<BooleanLiteral>;
695 auto var = dsl::p<Name>;
696 auto literal = dsl::p<AnyValue>;
698 return paren_expr |
boolean | var | literal | dsl::error<expected_operand>;
709 static constexpr
auto op = dsl::op<Ast::ExprUnaryArithmetic::negate>(
LEXY_LIT(
"-"));
715 static constexpr
auto op = [] {
719 return dsl::op<Ast::ExprBinaryArithmetic::times>(
times) /
720 dsl::op<Ast::ExprBinaryArithmetic::div>(div);
727 static constexpr
auto op = [] {
731 return dsl::op<Ast::ExprBinaryArithmetic::plus>(plus) /
732 dsl::op<Ast::ExprBinaryArithmetic::minus>(minus);
741 static constexpr
auto op = [] {
742 return dsl::op<Ast::ExprBinaryArithmetic::concat>(
LEXY_LIT(
".."));
751 static constexpr
auto op = [] {
755 return dsl::op<Ast::ExprUnaryArithmetic::complement>(complement) /
756 dsl::op<Ast::ExprUnaryArithmetic::logical_not>(logical_not);
764 static constexpr
auto op = [] {
767 return dsl::op<Ast::ExprBinaryArithmetic::bit_and>(
bit_and);
776 static constexpr
auto op = [] {
779 return dsl::op<Ast::ExprBinaryArithmetic::bit_or>(
bit_or) /
780 dsl::op<Ast::ExprBinaryArithmetic::bit_xor>(
LEXY_LIT(
"^"));
791 static constexpr
auto op = dsl::op<Ast::ExprComparison::equal>(
LEXY_LIT(
"==")) /
792 dsl::op<Ast::ExprComparison::not_equal>(
LEXY_LIT(
"!=")) /
793 dsl::op<Ast::ExprComparison::less>(
LEXY_LIT(
"<")) /
794 dsl::op<Ast::ExprComparison::greater>(
LEXY_LIT(
">")) /
795 dsl::op<Ast::ExprComparison::less_equal>(
LEXY_LIT(
"<=")) /
796 dsl::op<Ast::ExprComparison::greater_equal>(
LEXY_LIT(
">"
801 using operand = dsl::groups<math_sum, bit_or, string_concat>;
807 static constexpr
auto op =
808 dsl::op<Ast::ExprBinaryArithmetic::logic_or>(
LEXY_LIT(
"||")) /
809 dsl::op<Ast::ExprBinaryArithmetic::logic_and>(
LEXY_LIT(
"&&"));
820 static constexpr
auto op =
821 dsl::op<void>(
LEXY_LIT(
"?") >> (dsl::p<nested_expr> + dsl::lit_c<':'>));
828 static constexpr
auto op =
829 dsl::op<Ast::ExprAssignment::assign_create>(
LEXY_LIT(
":=")) /
830 dsl::op<Ast::ExprAssignment::assign_existing>(
832 dsl::op<Ast::ExprAssignment::assign_plus>(
LEXY_LIT(
"+=")) /
833 dsl::op<Ast::ExprAssignment::assign_minus>(
LEXY_LIT(
"-=")) /
834 dsl::op<Ast::ExprAssignment::assign_times>(
LEXY_LIT(
"*=")) /
835 dsl::op<Ast::ExprAssignment::assign_div>(
LEXY_LIT(
"/="));
846 lexy::fold_inplace<std::unique_ptr<Ast::ExprComparison>>(
847 [] {
return std::make_unique<Ast::ExprComparison>(); },
853 lexy::forward<Ast::expr_ptr>, lexy::new_<Ast::ExprLiteral, Ast::expr_ptr>,
854 lexy::new_<Ast::ExprName, Ast::expr_ptr>,
856 lexy::new_<Ast::ExprUnaryArithmetic, Ast::expr_ptr>,
857 lexy::new_<Ast::ExprBinaryArithmetic, Ast::expr_ptr>,
859 lexy::new_<Ast::ExprIf, Ast::expr_ptr>,
860 lexy::new_<Ast::ExprAssignment, Ast::expr_ptr>);
872 static constexpr
auto rule = [] {
879 static constexpr
auto value = lexy::as_list<std::vector<Ast::expr_ptr>>;