2
3
4
5
6
7
8
9
10
11
15#include "behaviortree_cpp/scripting/any_types.hpp"
16#include "behaviortree_cpp/scripting/script_parser.hpp"
28using expr_ptr = std::shared_ptr<
struct ExprBase>;
31inline double StringToDouble(
const Any& value,
const Environment& env)
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>;
57 virtual ~ExprBase() =
default;
61inline 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");
71 ExprLiteral(
Any v) : value(v)
84 explicit ExprName(std::string n) : name(std::move(n))
92 auto enum_ptr = env.enums->find(name);
93 if(enum_ptr != env.enums->end())
95 return Any(
double(enum_ptr->second));
99 auto any_ref = env.vars->getAnyLocked(name);
102 throw RuntimeError(StrCat(
"Variable not found: ", name));
104 return *any_ref.get();
118 explicit ExprUnaryArithmetic(op_t op, expr_ptr e) : op(op), rhs(std::move(e))
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())
144 throw RuntimeError(
"Invalid operator for std::string");
146 throw RuntimeError(
"ExprUnaryArithmetic: undefined");
168 const char* opStr()
const
198 explicit ExprBinaryArithmetic(expr_ptr lhs, op_t op, expr_ptr rhs)
199 : op(op), lhs(std::move(lhs)), rhs(std::move(rhs))
204 auto lhs_v = lhs->evaluate(env);
205 auto rhs_v = rhs->evaluate(env);
209 throw RuntimeError(ErrorNotInit(
"left", opStr()));
213 throw RuntimeError(ErrorNotInit(
"right", opStr()));
216 if(rhs_v.isNumber() && lhs_v.isNumber())
218 auto lv = lhs_v.cast<
double>();
219 auto rv = rhs_v.cast<
double>();
235 if(op == bit_and || op == bit_or || op == bit_xor)
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");
260 if(op == logic_or || op == logic_and)
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>());
295 throw RuntimeError(
"Operation not permitted");
303bool IsSame(
const T& lv,
const T& rv)
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;
328 const char* opStr(op_t op)
const
348 std::vector<op_t> ops;
349 std::vector<expr_ptr> operands;
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);
391 throw RuntimeError(ErrorNotInit(
"left", opStr(ops[i])));
395 throw RuntimeError(ErrorNotInit(
"right", opStr(ops[i])));
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())
410 auto lv = lhs_v.cast<SimpleString>();
411 auto rv = rhs_v.cast<SimpleString>();
412 if(!SwitchImpl(lv, rv, ops[i]))
417 else if(lhs_v.isString() && rhs_v.isNumber())
419 auto lv = StringToDouble(lhs_v, env);
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>();
429 auto rv = StringToDouble(rhs_v, env);
430 if(!SwitchImpl(lv, rv, ops[i]))
437 throw RuntimeError(StrCat(
"Can't mix different types in Comparison. "
439 BT::demangle(lhs_v.type()),
"] right operand [",
440 BT::demangle(rhs_v.type()),
"]"));
450 expr_ptr condition, then, else_;
452 explicit ExprIf(expr_ptr condition, expr_ptr then, expr_ptr else_)
453 : condition(std::move(condition)), then(std::move(then)), else_(std::move(else_))
458 const auto& v = condition->evaluate(env);
459 bool valid = (v.isType<SimpleString>() && v.cast<SimpleString>().size() > 0) ||
460 (v.cast<
double>() != 0.0);
463 return then->evaluate(env);
467 return else_->evaluate(env);
484 const char* opStr()
const
490 case assign_existing:
506 explicit ExprAssignment(expr_ptr _lhs, op_t op, expr_ptr _rhs)
507 : op(op), lhs(std::move(_lhs)), rhs(std::move(_rhs))
512 auto varname =
dynamic_cast<ExprName*>(lhs.get());
515 throw RuntimeError(
"Assignment left operand not a blackboard entry");
517 const auto& key = varname->name;
519 auto entry = env.vars->getEntry(key);
523 if(op == assign_create)
525 env.vars->createEntry(key, PortInfo());
526 entry = env.vars->getEntry(key);
529 throw LogicError(
"Bug: report");
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 [=]");
540 throw RuntimeError(msg);
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 [",
550 BT::demangle(dst_ptr->type()),
"]. ");
555 throw RuntimeError(ErrorNotInit(
"right", opStr()));
558 if(op == assign_create || op == assign_existing)
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())
579 auto num_value = StringToDouble(value, env);
580 *dst_ptr = Any(num_value);
584 auto msg = StrCat(errorPrefix(),
585 "\nThe right operand is a string, "
587 demangle(dst_ptr->type()));
588 throw RuntimeError(msg);
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 [",
601 BT::demangle(dst_ptr->type()),
"]");
602 throw RuntimeError(msg);
605 entry->sequence_id++;
606 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
612 throw RuntimeError(ErrorNotInit(
"left", opStr()));
616 Any temp_variable = *dst_ptr;
620 if(!temp_variable.isNumber())
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())
648 if(op == assign_plus)
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");
660 temp_variable.copyInto(*dst_ptr);
661 entry->sequence_id++;
662 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
668namespace BT::Scripting
673std::vector<Ast::expr_ptr> parseStatements(
const std::string& script);
Definition: safe_any.hpp:50
Definition: exceptions.h:61
Definition: simple_string.hpp:19
Definition: action_node.h:24
The Environment class is used to encapsulate the information and states needed by the scripting langu...
Definition: script_parser.hpp:32
Definition: operators.hpp:473
Definition: operators.hpp:54
Definition: operators.hpp:151
Definition: operators.hpp:317
Definition: operators.hpp:449
Definition: operators.hpp:68
Definition: operators.hpp:81
Definition: operators.hpp:109