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>();
140 return Any(
static_cast<
double>(~rhs_v.cast<int64_t>()));
142 catch(
const std::exception&)
144 throw RuntimeError(
"Number out of range for bitwise operation");
147 return Any(
static_cast<
double>(!
static_cast<
bool>(rv)));
150 else if(rhs_v.isString())
152 if(op == logical_not)
154 const auto str = rhs_v.cast<std::string>();
155 if(str ==
"true" || str ==
"True" || str ==
"TRUE" || str ==
"1")
159 if(str ==
"false" || str ==
"False" || str ==
"FALSE" || str ==
"0")
164 throw RuntimeError(
"Invalid operator for std::string");
166 throw RuntimeError(
"ExprUnaryArithmetic: undefined");
188 const char* opStr()
const
218 explicit ExprBinaryArithmetic(expr_ptr lhs, op_t op, expr_ptr rhs)
219 : op(op), lhs(std::move(lhs)), rhs(std::move(rhs))
224 auto lhs_v = lhs->evaluate(env);
225 auto rhs_v = rhs->evaluate(env);
229 throw RuntimeError(ErrorNotInit(
"left", opStr()));
233 throw RuntimeError(ErrorNotInit(
"right", opStr()));
236 if(rhs_v.isNumber() && lhs_v.isNumber())
238 auto lv = lhs_v.cast<
double>();
239 auto rv = rhs_v.cast<
double>();
255 if(op == bit_and || op == bit_or || op == bit_xor)
259 int64_t li = lhs_v.cast<int64_t>();
260 int64_t ri = rhs_v.cast<int64_t>();
264 return Any(
static_cast<
double>(li & ri));
266 return Any(
static_cast<
double>(li | ri));
268 return Any(
static_cast<
double>(li ^ ri));
275 throw RuntimeError(
"Binary operators are not allowed if "
276 "one of the operands is not an integer");
280 if(op == logic_or || op == logic_and)
284 auto lb = lhs_v.cast<
bool>();
285 auto rb = rhs_v.cast<
bool>();
289 return Any(
static_cast<
double>(lb || rb));
291 return Any(
static_cast<
double>(lb && rb));
298 throw RuntimeError(
"Logic operators are not allowed if "
299 "one of the operands is not castable to bool");
303 else if(rhs_v.isString() && lhs_v.isString() && op == plus)
305 return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
307 else if(op == concat && ((rhs_v.isString() && lhs_v.isString()) ||
308 (rhs_v.isString() && lhs_v.isNumber()) ||
309 (rhs_v.isNumber() && lhs_v.isString())))
311 return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
315 throw RuntimeError(
"Operation not permitted");
323bool IsSame(
const T& lv,
const T& rv)
325 if constexpr(std::is_same_v<
double, T>)
327 constexpr double EPS =
static_cast<
double>(std::numeric_limits<
float>::epsilon());
328 return std::abs(lv - rv) <= EPS;
348 const char* opStr(op_t op)
const
368 std::vector<op_t> ops;
369 std::vector<expr_ptr> operands;
373 auto SwitchImpl = [&](
const auto& lv,
const auto& rv, op_t op) {
404 auto lhs_v = operands[0]->evaluate(env);
405 for(
auto i = 0u; i != ops.size(); ++i)
407 auto rhs_v = operands[i + 1]->evaluate(env);
411 throw RuntimeError(ErrorNotInit(
"left", opStr(ops[i])));
415 throw RuntimeError(ErrorNotInit(
"right", opStr(ops[i])));
417 const Any False(0.0);
419 if(lhs_v.isNumber() && rhs_v.isNumber())
421 auto lv = lhs_v.cast<
double>();
422 auto rv = rhs_v.cast<
double>();
423 if(!SwitchImpl(lv, rv, ops[i]))
428 else if(lhs_v.isString() && rhs_v.isString())
430 auto lv = lhs_v.cast<SimpleString>();
431 auto rv = rhs_v.cast<SimpleString>();
432 if(!SwitchImpl(lv, rv, ops[i]))
437 else if(lhs_v.isString() && rhs_v.isNumber())
439 auto lv = StringToDouble(lhs_v, env);
440 auto rv = rhs_v.cast<
double>();
441 if(!SwitchImpl(lv, rv, ops[i]))
446 else if(lhs_v.isNumber() && rhs_v.isString())
448 auto lv = lhs_v.cast<
double>();
449 auto rv = StringToDouble(rhs_v, env);
450 if(!SwitchImpl(lv, rv, ops[i]))
457 throw RuntimeError(StrCat(
"Can't mix different types in Comparison. "
459 BT::demangle(lhs_v.type()),
"] right operand [",
460 BT::demangle(rhs_v.type()),
"]"));
470 expr_ptr condition, then, else_;
472 explicit ExprIf(expr_ptr condition, expr_ptr then, expr_ptr else_)
473 : condition(std::move(condition)), then(std::move(then)), else_(std::move(else_))
478 const auto& v = condition->evaluate(env);
479 bool valid = (v.isType<SimpleString>() && v.cast<SimpleString>().size() > 0) ||
480 (v.cast<
double>() != 0.0);
483 return then->evaluate(env);
487 return else_->evaluate(env);
504 const char* opStr()
const
510 case assign_existing:
526 explicit ExprAssignment(expr_ptr _lhs, op_t op, expr_ptr _rhs)
527 : op(op), lhs(std::move(_lhs)), rhs(std::move(_rhs))
532 auto varname =
dynamic_cast<ExprName*>(lhs.get());
535 throw RuntimeError(
"Assignment left operand not a blackboard entry");
537 const auto& key = varname->name;
539 auto entry = env.vars->getEntry(key);
543 if(op == assign_create)
545 env.vars->createEntry(key, PortInfo());
546 entry = env.vars->getEntry(key);
549 throw LogicError(
"Bug: report");
555 auto msg = StrCat(
"The blackboard entry [", key,
556 "] doesn't exist, yet.\n"
557 "If you want to create a new one, "
559 "[:=] instead of [=]");
560 throw RuntimeError(msg);
563 auto value = rhs->evaluate(env);
565 std::scoped_lock lock(entry->entry_mutex);
566 auto* dst_ptr = &entry->value;
568 auto errorPrefix = [dst_ptr, &key]() {
569 return StrCat(
"Error assigning a value to entry [", key,
"] with type [",
570 BT::demangle(dst_ptr->type()),
"]. ");
575 throw RuntimeError(ErrorNotInit(
"right", opStr()));
578 if(op == assign_create || op == assign_existing)
582 if(dst_ptr->empty() && entry->info.type() ==
typeid(AnyTypeAllowed))
586 else if(value.isString() && !dst_ptr->isString())
590 auto const str = value.cast<std::string>();
591 const auto* entry_info = env.vars->entryInfo(key);
593 if(
auto converter = entry_info->converter())
595 *dst_ptr = converter(str);
597 else if(dst_ptr->isNumber())
599 auto num_value = StringToDouble(value, env);
600 *dst_ptr = Any(num_value);
604 auto msg = StrCat(errorPrefix(),
605 "\nThe right operand is a string, "
607 demangle(dst_ptr->type()));
608 throw RuntimeError(msg);
615 value.copyInto(*dst_ptr);
617 catch(std::exception&)
619 auto msg = StrCat(errorPrefix(),
"\nThe right operand has type [",
620 BT::demangle(value.type()),
"] and can't be converted to [",
621 BT::demangle(dst_ptr->type()),
"]");
622 throw RuntimeError(msg);
625 entry->sequence_id++;
626 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
632 throw RuntimeError(ErrorNotInit(
"left", opStr()));
636 Any temp_variable = *dst_ptr;
640 if(!temp_variable.isNumber())
642 throw RuntimeError(
"This Assignment operator can't be used "
643 "with a non-numeric type");
646 auto lv = temp_variable.cast<
double>();
647 auto rv = value.cast<
double>();
651 temp_variable = Any(lv + rv);
654 temp_variable = Any(lv - rv);
657 temp_variable = Any(lv * rv);
660 temp_variable = Any(lv / rv);
666 else if(value.isString())
668 if(op == assign_plus)
670 auto lv = temp_variable.cast<std::string>();
671 auto rv = value.cast<std::string>();
672 temp_variable = Any(lv + rv);
676 throw RuntimeError(
"Operator not supported for strings");
680 temp_variable.copyInto(*dst_ptr);
681 entry->sequence_id++;
682 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
688namespace BT::Scripting
693std::vector<Ast::expr_ptr> parseStatements(
const std::string& script);
Definition: safe_any.hpp:57
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:493
Definition: operators.hpp:54
Definition: operators.hpp:171
Definition: operators.hpp:337
Definition: operators.hpp:469
Definition: operators.hpp:68
Definition: operators.hpp:81
Definition: operators.hpp:109