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 if(rv >
static_cast<double>(std::numeric_limits<int64_t>::max()) ||
133 rv <
static_cast<double>(std::numeric_limits<int64_t>::min()))
135 throw RuntimeError(
"Number out of range for bitwise operation");
137 return Any(
static_cast<double>(~
static_cast<int64_t
>(rv)));
139 return Any(
static_cast<double>(!
static_cast<bool>(rv)));
142 else if(rhs_v.isString())
204 auto lhs_v =
lhs->evaluate(env);
205 auto rhs_v =
rhs->evaluate(env);
216 if(rhs_v.isNumber() && lhs_v.isNumber())
218 auto lv = lhs_v.cast<
double>();
219 auto rv = rhs_v.cast<
double>();
239 int64_t li = lhs_v.cast<int64_t>();
240 int64_t ri = rhs_v.cast<int64_t>();
244 return Any(
static_cast<double>(li & ri));
246 return Any(
static_cast<double>(li | ri));
248 return Any(
static_cast<double>(li ^ ri));
255 throw RuntimeError(
"Binary operators are not allowed if "
256 "one of the operands is not an integer");
264 auto lb = lhs_v.cast<
bool>();
265 auto rb = rhs_v.cast<
bool>();
269 return Any(
static_cast<double>(lb || rb));
271 return Any(
static_cast<double>(lb && rb));
278 throw RuntimeError(
"Logic operators are not allowed if "
279 "one of the operands is not castable to bool");
283 else if(rhs_v.isString() && lhs_v.isString() &&
op ==
plus)
285 return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
287 else if(
op ==
concat && ((rhs_v.isString() && lhs_v.isString()) ||
288 (rhs_v.isString() && lhs_v.isNumber()) ||
289 (rhs_v.isNumber() && lhs_v.isString())))
291 return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
302 template <
typename T>
305 if constexpr(std::is_same_v<double, T>)
307 constexpr
double EPS =
static_cast<double>(std::numeric_limits<float>::epsilon());
308 return std::abs(lv - rv) <= EPS;
353 auto SwitchImpl = [&](
const auto& lv,
const auto& rv,
op_t op) {
384 auto lhs_v =
operands[0]->evaluate(env);
385 for(
auto i = 0u; i !=
ops.size(); ++i)
387 auto rhs_v =
operands[i + 1]->evaluate(env);
397 const Any False(0.0);
399 if(lhs_v.isNumber() && rhs_v.isNumber())
401 auto lv = lhs_v.cast<
double>();
402 auto rv = rhs_v.cast<
double>();
403 if(!SwitchImpl(lv, rv,
ops[i]))
408 else if(lhs_v.isString() && rhs_v.isString())
412 if(!SwitchImpl(lv, rv,
ops[i]))
417 else if(lhs_v.isString() && rhs_v.isNumber())
420 auto rv = rhs_v.cast<
double>();
421 if(!SwitchImpl(lv, rv,
ops[i]))
426 else if(lhs_v.isNumber() && rhs_v.isString())
428 auto lv = lhs_v.
cast<
double>();
430 if(!SwitchImpl(lv, rv,
ops[i]))
458 const auto& v =
condition->evaluate(env);
460 (v.cast<
double>() != 0.0);
463 return then->evaluate(env);
467 return else_->evaluate(env);
515 throw RuntimeError(
"Assignment left operand not a blackboard entry");
517 const auto& key = varname->name;
519 auto entry = env.
vars->getEntry(key);
526 entry = env.
vars->getEntry(key);
535 auto msg =
StrCat(
"The blackboard entry [", key,
536 "] doesn't exist, yet.\n"
537 "If you want to create a new one, "
539 "[:=] instead of [=]");
543 auto value =
rhs->evaluate(env);
545 std::scoped_lock lock(entry->entry_mutex);
546 auto* dst_ptr = &entry->value;
548 auto errorPrefix = [dst_ptr, &key]() {
549 return StrCat(
"Error assigning a value to entry [", key,
"] with type [",
562 if(dst_ptr->empty() && entry->info.type() ==
typeid(
AnyTypeAllowed))
566 else if(value.isString() && !dst_ptr->isString())
570 auto const str = value.cast<std::string>();
571 const auto* entry_info = env.
vars->entryInfo(key);
573 if(
auto converter = entry_info->converter())
575 *dst_ptr = converter(str);
577 else if(dst_ptr->isNumber())
580 *dst_ptr =
Any(num_value);
584 auto msg =
StrCat(errorPrefix(),
585 "\nThe right operand is a string, "
595 value.copyInto(*dst_ptr);
597 catch(std::exception&)
599 auto msg =
StrCat(errorPrefix(),
"\nThe right operand has type [",
600 BT::demangle(value.type()),
"] and can't be converted to [",
605 entry->sequence_id++;
606 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
616 Any temp_variable = *dst_ptr;
622 throw RuntimeError(
"This Assignment operator can't be used "
623 "with a non-numeric type");
626 auto lv = temp_variable.
cast<
double>();
627 auto rv = value.cast<
double>();
631 temp_variable =
Any(lv + rv);
634 temp_variable =
Any(lv - rv);
637 temp_variable =
Any(lv * rv);
640 temp_variable =
Any(lv / rv);
646 else if(value.isString())
650 auto lv = temp_variable.
cast<std::string>();
651 auto rv = value.cast<std::string>();
652 temp_variable =
Any(lv + rv);
656 throw RuntimeError(
"Operator not supported for strings");
661 entry->sequence_id++;
662 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
670 namespace dsl = lexy::dsl;
681 static constexpr
auto rule = dsl::recurse<struct Expression>;
683 static constexpr
auto value = lexy::forward<Ast::expr_ptr>;
693 static constexpr
auto name =
"expected operand";
697 static constexpr
auto atom = [] {
699 auto boolean = dsl::p<BooleanLiteral>;
700 auto var = dsl::p<Name>;
701 auto literal = dsl::p<AnyValue>;
703 return paren_expr |
boolean | var | literal | dsl::error<expected_operand>;
714 static constexpr
auto op = dsl::op<Ast::ExprUnaryArithmetic::negate>(
LEXY_LIT(
"-"));
720 static constexpr
auto op = [] {
724 return dsl::op<Ast::ExprBinaryArithmetic::times>(
times) /
725 dsl::op<Ast::ExprBinaryArithmetic::div>(div);
732 static constexpr
auto op = [] {
736 return dsl::op<Ast::ExprBinaryArithmetic::plus>(plus) /
737 dsl::op<Ast::ExprBinaryArithmetic::minus>(minus);
746 static constexpr
auto op = [] {
747 return dsl::op<Ast::ExprBinaryArithmetic::concat>(
LEXY_LIT(
".."));
756 static constexpr
auto op = [] {
760 return dsl::op<Ast::ExprUnaryArithmetic::complement>(complement) /
761 dsl::op<Ast::ExprUnaryArithmetic::logical_not>(logical_not);
769 static constexpr
auto op = [] {
772 return dsl::op<Ast::ExprBinaryArithmetic::bit_and>(
bit_and);
781 static constexpr
auto op = [] {
784 return dsl::op<Ast::ExprBinaryArithmetic::bit_or>(
bit_or) /
785 dsl::op<Ast::ExprBinaryArithmetic::bit_xor>(
LEXY_LIT(
"^"));
796 static constexpr
auto op = dsl::op<Ast::ExprComparison::equal>(
LEXY_LIT(
"==")) /
797 dsl::op<Ast::ExprComparison::not_equal>(
LEXY_LIT(
"!=")) /
798 dsl::op<Ast::ExprComparison::less>(
LEXY_LIT(
"<")) /
799 dsl::op<Ast::ExprComparison::greater>(
LEXY_LIT(
">")) /
800 dsl::op<Ast::ExprComparison::less_equal>(
LEXY_LIT(
"<=")) /
801 dsl::op<Ast::ExprComparison::greater_equal>(
LEXY_LIT(
">"
806 using operand = dsl::groups<math_sum, bit_or, string_concat>;
812 static constexpr
auto op =
813 dsl::op<Ast::ExprBinaryArithmetic::logic_or>(
LEXY_LIT(
"||")) /
814 dsl::op<Ast::ExprBinaryArithmetic::logic_and>(
LEXY_LIT(
"&&"));
825 static constexpr
auto op =
826 dsl::op<void>(
LEXY_LIT(
"?") >> (dsl::p<nested_expr> + dsl::lit_c<':'>));
833 static constexpr
auto op =
834 dsl::op<Ast::ExprAssignment::assign_create>(
LEXY_LIT(
":=")) /
835 dsl::op<Ast::ExprAssignment::assign_existing>(
837 dsl::op<Ast::ExprAssignment::assign_plus>(
LEXY_LIT(
"+=")) /
838 dsl::op<Ast::ExprAssignment::assign_minus>(
LEXY_LIT(
"-=")) /
839 dsl::op<Ast::ExprAssignment::assign_times>(
LEXY_LIT(
"*=")) /
840 dsl::op<Ast::ExprAssignment::assign_div>(
LEXY_LIT(
"/="));
851 lexy::fold_inplace<std::unique_ptr<Ast::ExprComparison>>(
852 [] {
return std::make_unique<Ast::ExprComparison>(); },
858 lexy::forward<Ast::expr_ptr>, lexy::new_<Ast::ExprLiteral, Ast::expr_ptr>,
859 lexy::new_<Ast::ExprName, Ast::expr_ptr>,
861 lexy::new_<Ast::ExprUnaryArithmetic, Ast::expr_ptr>,
862 lexy::new_<Ast::ExprBinaryArithmetic, Ast::expr_ptr>,
864 lexy::new_<Ast::ExprIf, Ast::expr_ptr>,
865 lexy::new_<Ast::ExprAssignment, Ast::expr_ptr>);
877 static constexpr
auto rule = [] {
884 static constexpr
auto value = lexy::as_list<std::vector<Ast::expr_ptr>>;