LLVMFuzzerTestOneInput:
   13|  5.55k|{
   14|  5.55k|  if(size < 4)
  ------------------
  |  Branch (14:6): [True: 2, False: 5.55k]
  ------------------
   15|      2|  {
   16|      2|    return 0;
   17|      2|  }
   18|       |
   19|  5.55k|  FuzzedDataProvider fuzz_data(data, size);
   20|       |
   21|  5.55k|  try
   22|  5.55k|  {
   23|  5.55k|    BT::Ast::Environment env;
   24|  5.55k|    env.vars = BT::Blackboard::create();
   25|  5.55k|    env.enums = std::make_shared<BT::EnumsTable>();
   26|       |
   27|       |    // Add some test variables to the blackboard
   28|  5.55k|    env.vars->set("test_int", 42);
   29|  5.55k|    env.vars->set("test_double", 3.14);
   30|  5.55k|    env.vars->set("test_bool", true);
   31|  5.55k|    env.vars->set("test_string", std::string("test"));
   32|       |
   33|       |    // Add some test enums
   34|  5.55k|    (*env.enums)["RUNNING"] = 0;
   35|  5.55k|    (*env.enums)["SUCCESS"] = 1;
   36|  5.55k|    (*env.enums)["FAILURE"] = 2;
   37|       |
   38|  5.55k|    std::string script = fuzz_data.ConsumeRandomLengthString();
   39|       |
   40|  5.55k|    auto validation_result = BT::ValidateScript(script);
   41|       |
   42|  5.55k|    if(!validation_result)
  ------------------
  |  Branch (42:8): [True: 1.55k, False: 3.99k]
  ------------------
   43|  1.55k|    {
   44|  1.55k|      auto parsed_script = BT::ParseScript(script);
   45|  1.55k|      if(parsed_script)
  ------------------
  |  Branch (45:10): [True: 0, False: 1.55k]
  ------------------
   46|      0|      {
   47|      0|        try
   48|      0|        {
   49|      0|          auto result = parsed_script.value()(env);
   50|       |
   51|      0|          if(result.isNumber())
  ------------------
  |  Branch (51:14): [True: 0, False: 0]
  ------------------
   52|      0|          {
   53|      0|            volatile auto num = result.cast<double>();
   54|      0|          }
   55|       |
   56|      0|          env.vars->set("result", result);
   57|       |
   58|      0|          BT::Any read_back;
   59|      0|          (void)env.vars->get("result", read_back);
   60|      0|        }
   61|      0|        catch(const BT::RuntimeError&)  // NOLINT(bugprone-empty-catch)
   62|      0|        {
   63|       |          // Intentionally empty - fuzzer expects exceptions
   64|      0|        }
   65|      0|      }
   66|  1.55k|    }
   67|       |
   68|  5.55k|    BT::ParseScriptAndExecute(env, script);
   69|  5.55k|  }
   70|  5.55k|  catch(const std::exception&)  // NOLINT(bugprone-empty-catch)
   71|  5.55k|  {
   72|       |    // Intentionally empty - fuzzer expects exceptions
   73|    211|  }
   74|       |
   75|  5.55k|  return 0;
   76|  5.55k|}

_ZN2BT23GetAnyFromStringFunctorIiEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  234|  5.55k|{
  235|       |  if constexpr(std::is_constructible_v<StringView, T>)
  236|       |  {
  237|       |    return [](StringView str) { return Any(str); };
  238|       |  }
  239|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  240|       |  {
  241|       |    return {};
  242|       |  }
  243|       |  else
  244|  5.55k|  {
  245|  5.55k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  246|  5.55k|  }
  247|  5.55k|}
_ZN2BT8PortInfoC2ENS_13PortDirectionESt10type_indexSt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEE:
  428|  16.6k|    : TypeInfo(type_info, conv), direction_(direction)
  429|  16.6k|  {}
_ZN2BT8TypeInfoC2ESt10type_indexSt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEE:
  386|  16.6k|    : type_info_(type_info), converter_(conv), type_str_(BT::demangle(type_info))
  387|  16.6k|  {}
_ZN2BT23GetAnyFromStringFunctorIdEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  234|  5.55k|{
  235|       |  if constexpr(std::is_constructible_v<StringView, T>)
  236|       |  {
  237|       |    return [](StringView str) { return Any(str); };
  238|       |  }
  239|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  240|       |  {
  241|       |    return {};
  242|       |  }
  243|       |  else
  244|  5.55k|  {
  245|  5.55k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  246|  5.55k|  }
  247|  5.55k|}
_ZN2BT23GetAnyFromStringFunctorIbEESt8functionIFNS_3AnyESt17basic_string_viewIcSt11char_traitsIcEEEEv:
  234|  5.55k|{
  235|       |  if constexpr(std::is_constructible_v<StringView, T>)
  236|       |  {
  237|       |    return [](StringView str) { return Any(str); };
  238|       |  }
  239|       |  else if constexpr(std::is_same_v<BT::AnyTypeAllowed, T> || std::is_enum_v<T>)
  240|       |  {
  241|       |    return {};
  242|       |  }
  243|       |  else
  244|  5.55k|  {
  245|  5.55k|    return [](StringView str) { return Any(convertFromString<T>(str)); };
  246|  5.55k|  }
  247|  5.55k|}
_ZN2BT8PortInfoC2ENS_13PortDirectionE:
  424|  14.9k|    : TypeInfo(), direction_(direction)
  425|  14.9k|  {}
_ZN2BT8TypeInfoC2Ev:
  382|  14.9k|  TypeInfo() : type_info_(typeid(AnyTypeAllowed)), type_str_("AnyTypeAllowed")
  383|  14.9k|  {}
_ZNK2BT8TypeInfo9converterEv:
  410|    647|  {
  411|    647|    return converter_;
  412|    647|  }

_ZN2BT10Blackboard6createESt10shared_ptrIS0_E:
   75|  5.55k|  {
   76|  5.55k|    return std::shared_ptr<Blackboard>(new Blackboard(parent));
   77|  5.55k|  }
_ZN2BT10BlackboardC2ESt10shared_ptrIS0_E:
   41|  5.55k|  Blackboard(Blackboard::Ptr parent) : parent_bb_(parent)
   42|  5.55k|  {}
_ZN2BT10BlackboardD2Ev:
   79|  5.55k|  virtual ~Blackboard() = default;
_ZN2BT10Blackboard3setIiEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  273|  5.55k|{
  274|  5.55k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (274:6): [True: 0, False: 5.55k]
  ------------------
  275|      0|  {
  276|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  277|      0|    return;
  278|      0|  }
  279|  5.55k|  std::shared_lock storage_lock(storage_mutex_);
  280|       |
  281|       |  // check local storage
  282|  5.55k|  auto it = storage_.find(key);
  283|  5.55k|  if(it == storage_.end())
  ------------------
  |  Branch (283:6): [True: 5.55k, False: 0]
  ------------------
  284|  5.55k|  {
  285|       |    // create a new entry
  286|  5.55k|    Any new_value(value);
  287|  5.55k|    storage_lock.unlock();
  288|  5.55k|    std::shared_ptr<Blackboard::Entry> entry;
  289|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  290|       |    if constexpr(std::is_same_v<std::string, T>)
  291|       |    {
  292|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  293|       |    }
  294|       |    else
  295|  5.55k|    {
  296|  5.55k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  297|  5.55k|                        GetAnyFromStringFunctor<T>());
  298|  5.55k|      entry = createEntryImpl(key, new_port);
  299|  5.55k|    }
  300|       |
  301|       |    // Lock entry_mutex before writing to prevent data races with
  302|       |    // concurrent readers (BUG-1/BUG-8 fix).
  303|  5.55k|    std::scoped_lock entry_lock(entry->entry_mutex);
  304|  5.55k|    entry->value = new_value;
  305|  5.55k|    entry->sequence_id++;
  306|  5.55k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  307|  5.55k|  }
  308|      0|  else
  309|      0|  {
  310|       |    // this is not the first time we set this entry, we need to check
  311|       |    // if the type is the same or not.
  312|       |    // Copy shared_ptr to prevent use-after-free if another thread
  313|       |    // calls unset() while we hold the reference (BUG-2 fix).
  314|      0|    auto entry_ptr = it->second;
  315|      0|    storage_lock.unlock();
  316|      0|    Entry& entry = *entry_ptr;
  317|       |
  318|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  319|       |
  320|      0|    Any& previous_any = entry.value;
  321|      0|    Any new_value(value);
  322|       |
  323|       |    // special case: entry exists but it is not strongly typed... yet
  324|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (324:8): [True: 0, False: 0]
  ------------------
  325|      0|    {
  326|       |      // Use the new type to create a new entry that is strongly typed.
  327|      0|      entry.info = TypeInfo::Create<T>();
  328|      0|      entry.sequence_id++;
  329|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  330|      0|      previous_any = std::move(new_value);
  331|      0|      return;
  332|      0|    }
  333|       |
  334|      0|    std::type_index previous_type = entry.info.type();
  335|       |
  336|       |    // check type mismatch
  337|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:55): [True: 0, False: 0]
  ------------------
  338|      0|    {
  339|      0|      bool mismatching = true;
  340|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (340:10): [Folded, False: 0]
  ------------------
  341|      0|      {
  342|      0|        Any any_from_string = entry.info.parseString(value);
  343|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (343:12): [True: 0, False: 0]
  ------------------
  344|      0|        {
  345|      0|          mismatching = false;
  346|      0|          new_value = std::move(any_from_string);
  347|      0|        }
  348|      0|      }
  349|       |      // check if we are doing a safe cast between numbers
  350|       |      // for instance, it is safe to use int(100) to set
  351|       |      // a uint8_t port, but not int(-42) or int(300)
  352|       |      if constexpr(std::is_arithmetic_v<T>)
  353|      0|      {
  354|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  |  Branch (354:27): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|        }
  358|      0|      }
  359|       |
  360|      0|      if(mismatching)
  ------------------
  |  Branch (360:10): [True: 0, False: 0]
  ------------------
  361|      0|      {
  362|      0|        debugMessage();
  363|       |
  364|      0|        auto msg = StrCat("Blackboard::set(", key,
  365|      0|                          "): once declared, "
  366|      0|                          "the type of a port shall not change. "
  367|      0|                          "Previously declared type [",
  368|      0|                          BT::demangle(previous_type), "], current type [",
  369|      0|                          BT::demangle(typeid(T)), "]");
  370|      0|        throw LogicError(msg);
  371|      0|      }
  372|      0|    }
  373|       |    // if doing set<BT::Any>, skip type check
  374|       |    if constexpr(std::is_same_v<Any, T>)
  375|       |    {
  376|       |      previous_any = new_value;
  377|       |    }
  378|       |    else
  379|      0|    {
  380|       |      // copy only if the type is compatible
  381|      0|      new_value.copyInto(previous_any);
  382|      0|    }
  383|      0|    entry.sequence_id++;
  384|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  385|      0|  }
  386|  5.55k|}
_ZN2BT10Blackboard3setIdEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  273|  5.55k|{
  274|  5.55k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (274:6): [True: 0, False: 5.55k]
  ------------------
  275|      0|  {
  276|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  277|      0|    return;
  278|      0|  }
  279|  5.55k|  std::shared_lock storage_lock(storage_mutex_);
  280|       |
  281|       |  // check local storage
  282|  5.55k|  auto it = storage_.find(key);
  283|  5.55k|  if(it == storage_.end())
  ------------------
  |  Branch (283:6): [True: 5.55k, False: 0]
  ------------------
  284|  5.55k|  {
  285|       |    // create a new entry
  286|  5.55k|    Any new_value(value);
  287|  5.55k|    storage_lock.unlock();
  288|  5.55k|    std::shared_ptr<Blackboard::Entry> entry;
  289|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  290|       |    if constexpr(std::is_same_v<std::string, T>)
  291|       |    {
  292|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  293|       |    }
  294|       |    else
  295|  5.55k|    {
  296|  5.55k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  297|  5.55k|                        GetAnyFromStringFunctor<T>());
  298|  5.55k|      entry = createEntryImpl(key, new_port);
  299|  5.55k|    }
  300|       |
  301|       |    // Lock entry_mutex before writing to prevent data races with
  302|       |    // concurrent readers (BUG-1/BUG-8 fix).
  303|  5.55k|    std::scoped_lock entry_lock(entry->entry_mutex);
  304|  5.55k|    entry->value = new_value;
  305|  5.55k|    entry->sequence_id++;
  306|  5.55k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  307|  5.55k|  }
  308|      0|  else
  309|      0|  {
  310|       |    // this is not the first time we set this entry, we need to check
  311|       |    // if the type is the same or not.
  312|       |    // Copy shared_ptr to prevent use-after-free if another thread
  313|       |    // calls unset() while we hold the reference (BUG-2 fix).
  314|      0|    auto entry_ptr = it->second;
  315|      0|    storage_lock.unlock();
  316|      0|    Entry& entry = *entry_ptr;
  317|       |
  318|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  319|       |
  320|      0|    Any& previous_any = entry.value;
  321|      0|    Any new_value(value);
  322|       |
  323|       |    // special case: entry exists but it is not strongly typed... yet
  324|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (324:8): [True: 0, False: 0]
  ------------------
  325|      0|    {
  326|       |      // Use the new type to create a new entry that is strongly typed.
  327|      0|      entry.info = TypeInfo::Create<T>();
  328|      0|      entry.sequence_id++;
  329|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  330|      0|      previous_any = std::move(new_value);
  331|      0|      return;
  332|      0|    }
  333|       |
  334|      0|    std::type_index previous_type = entry.info.type();
  335|       |
  336|       |    // check type mismatch
  337|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:55): [True: 0, False: 0]
  ------------------
  338|      0|    {
  339|      0|      bool mismatching = true;
  340|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (340:10): [Folded, False: 0]
  ------------------
  341|      0|      {
  342|      0|        Any any_from_string = entry.info.parseString(value);
  343|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (343:12): [True: 0, False: 0]
  ------------------
  344|      0|        {
  345|      0|          mismatching = false;
  346|      0|          new_value = std::move(any_from_string);
  347|      0|        }
  348|      0|      }
  349|       |      // check if we are doing a safe cast between numbers
  350|       |      // for instance, it is safe to use int(100) to set
  351|       |      // a uint8_t port, but not int(-42) or int(300)
  352|       |      if constexpr(std::is_arithmetic_v<T>)
  353|      0|      {
  354|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  |  Branch (354:27): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|        }
  358|      0|      }
  359|       |
  360|      0|      if(mismatching)
  ------------------
  |  Branch (360:10): [True: 0, False: 0]
  ------------------
  361|      0|      {
  362|      0|        debugMessage();
  363|       |
  364|      0|        auto msg = StrCat("Blackboard::set(", key,
  365|      0|                          "): once declared, "
  366|      0|                          "the type of a port shall not change. "
  367|      0|                          "Previously declared type [",
  368|      0|                          BT::demangle(previous_type), "], current type [",
  369|      0|                          BT::demangle(typeid(T)), "]");
  370|      0|        throw LogicError(msg);
  371|      0|      }
  372|      0|    }
  373|       |    // if doing set<BT::Any>, skip type check
  374|       |    if constexpr(std::is_same_v<Any, T>)
  375|       |    {
  376|       |      previous_any = new_value;
  377|       |    }
  378|       |    else
  379|      0|    {
  380|       |      // copy only if the type is compatible
  381|      0|      new_value.copyInto(previous_any);
  382|      0|    }
  383|      0|    entry.sequence_id++;
  384|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  385|      0|  }
  386|  5.55k|}
_ZN2BT10Blackboard3setIbEEvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_:
  273|  5.55k|{
  274|  5.55k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (274:6): [True: 0, False: 5.55k]
  ------------------
  275|      0|  {
  276|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  277|      0|    return;
  278|      0|  }
  279|  5.55k|  std::shared_lock storage_lock(storage_mutex_);
  280|       |
  281|       |  // check local storage
  282|  5.55k|  auto it = storage_.find(key);
  283|  5.55k|  if(it == storage_.end())
  ------------------
  |  Branch (283:6): [True: 5.55k, False: 0]
  ------------------
  284|  5.55k|  {
  285|       |    // create a new entry
  286|  5.55k|    Any new_value(value);
  287|  5.55k|    storage_lock.unlock();
  288|  5.55k|    std::shared_ptr<Blackboard::Entry> entry;
  289|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  290|       |    if constexpr(std::is_same_v<std::string, T>)
  291|       |    {
  292|       |      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  293|       |    }
  294|       |    else
  295|  5.55k|    {
  296|  5.55k|      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  297|  5.55k|                        GetAnyFromStringFunctor<T>());
  298|  5.55k|      entry = createEntryImpl(key, new_port);
  299|  5.55k|    }
  300|       |
  301|       |    // Lock entry_mutex before writing to prevent data races with
  302|       |    // concurrent readers (BUG-1/BUG-8 fix).
  303|  5.55k|    std::scoped_lock entry_lock(entry->entry_mutex);
  304|  5.55k|    entry->value = new_value;
  305|  5.55k|    entry->sequence_id++;
  306|  5.55k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  307|  5.55k|  }
  308|      0|  else
  309|      0|  {
  310|       |    // this is not the first time we set this entry, we need to check
  311|       |    // if the type is the same or not.
  312|       |    // Copy shared_ptr to prevent use-after-free if another thread
  313|       |    // calls unset() while we hold the reference (BUG-2 fix).
  314|      0|    auto entry_ptr = it->second;
  315|      0|    storage_lock.unlock();
  316|      0|    Entry& entry = *entry_ptr;
  317|       |
  318|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  319|       |
  320|      0|    Any& previous_any = entry.value;
  321|      0|    Any new_value(value);
  322|       |
  323|       |    // special case: entry exists but it is not strongly typed... yet
  324|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (324:8): [True: 0, False: 0]
  ------------------
  325|      0|    {
  326|       |      // Use the new type to create a new entry that is strongly typed.
  327|      0|      entry.info = TypeInfo::Create<T>();
  328|      0|      entry.sequence_id++;
  329|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  330|      0|      previous_any = std::move(new_value);
  331|      0|      return;
  332|      0|    }
  333|       |
  334|      0|    std::type_index previous_type = entry.info.type();
  335|       |
  336|       |    // check type mismatch
  337|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:55): [True: 0, False: 0]
  ------------------
  338|      0|    {
  339|      0|      bool mismatching = true;
  340|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (340:10): [Folded, False: 0]
  ------------------
  341|      0|      {
  342|      0|        Any any_from_string = entry.info.parseString(value);
  343|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (343:12): [True: 0, False: 0]
  ------------------
  344|      0|        {
  345|      0|          mismatching = false;
  346|      0|          new_value = std::move(any_from_string);
  347|      0|        }
  348|      0|      }
  349|       |      // check if we are doing a safe cast between numbers
  350|       |      // for instance, it is safe to use int(100) to set
  351|       |      // a uint8_t port, but not int(-42) or int(300)
  352|       |      if constexpr(std::is_arithmetic_v<T>)
  353|      0|      {
  354|      0|        if(mismatching && isCastingSafe(previous_type, value))
  ------------------
  |  Branch (354:12): [True: 0, False: 0]
  |  Branch (354:27): [True: 0, False: 0]
  ------------------
  355|      0|        {
  356|      0|          mismatching = false;
  357|      0|        }
  358|      0|      }
  359|       |
  360|      0|      if(mismatching)
  ------------------
  |  Branch (360:10): [True: 0, False: 0]
  ------------------
  361|      0|      {
  362|      0|        debugMessage();
  363|       |
  364|      0|        auto msg = StrCat("Blackboard::set(", key,
  365|      0|                          "): once declared, "
  366|      0|                          "the type of a port shall not change. "
  367|      0|                          "Previously declared type [",
  368|      0|                          BT::demangle(previous_type), "], current type [",
  369|      0|                          BT::demangle(typeid(T)), "]");
  370|      0|        throw LogicError(msg);
  371|      0|      }
  372|      0|    }
  373|       |    // if doing set<BT::Any>, skip type check
  374|       |    if constexpr(std::is_same_v<Any, T>)
  375|       |    {
  376|       |      previous_any = new_value;
  377|       |    }
  378|       |    else
  379|      0|    {
  380|       |      // copy only if the type is compatible
  381|      0|      new_value.copyInto(previous_any);
  382|      0|    }
  383|      0|    entry.sequence_id++;
  384|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  385|      0|  }
  386|  5.55k|}
_ZN2BT10Blackboard3setINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEvRKS7_RKT_:
  273|  5.55k|{
  274|  5.55k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (274:6): [True: 0, False: 5.55k]
  ------------------
  275|      0|  {
  276|      0|    rootBlackboard()->set(key.substr(1, key.size() - 1), value);
  277|      0|    return;
  278|      0|  }
  279|  5.55k|  std::shared_lock storage_lock(storage_mutex_);
  280|       |
  281|       |  // check local storage
  282|  5.55k|  auto it = storage_.find(key);
  283|  5.55k|  if(it == storage_.end())
  ------------------
  |  Branch (283:6): [True: 5.55k, False: 0]
  ------------------
  284|  5.55k|  {
  285|       |    // create a new entry
  286|  5.55k|    Any new_value(value);
  287|  5.55k|    storage_lock.unlock();
  288|  5.55k|    std::shared_ptr<Blackboard::Entry> entry;
  289|       |    // if a new generic port is created with a string, it's type should be AnyTypeAllowed
  290|       |    if constexpr(std::is_same_v<std::string, T>)
  291|  5.55k|    {
  292|  5.55k|      entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
  293|       |    }
  294|       |    else
  295|       |    {
  296|       |      PortInfo new_port(PortDirection::INOUT, new_value.type(),
  297|       |                        GetAnyFromStringFunctor<T>());
  298|       |      entry = createEntryImpl(key, new_port);
  299|       |    }
  300|       |
  301|       |    // Lock entry_mutex before writing to prevent data races with
  302|       |    // concurrent readers (BUG-1/BUG-8 fix).
  303|  5.55k|    std::scoped_lock entry_lock(entry->entry_mutex);
  304|  5.55k|    entry->value = new_value;
  305|  5.55k|    entry->sequence_id++;
  306|  5.55k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  307|  5.55k|  }
  308|      0|  else
  309|      0|  {
  310|       |    // this is not the first time we set this entry, we need to check
  311|       |    // if the type is the same or not.
  312|       |    // Copy shared_ptr to prevent use-after-free if another thread
  313|       |    // calls unset() while we hold the reference (BUG-2 fix).
  314|      0|    auto entry_ptr = it->second;
  315|      0|    storage_lock.unlock();
  316|      0|    Entry& entry = *entry_ptr;
  317|       |
  318|      0|    std::scoped_lock scoped_lock(entry.entry_mutex);
  319|       |
  320|      0|    Any& previous_any = entry.value;
  321|      0|    Any new_value(value);
  322|       |
  323|       |    // special case: entry exists but it is not strongly typed... yet
  324|      0|    if(!entry.info.isStronglyTyped())
  ------------------
  |  Branch (324:8): [True: 0, False: 0]
  ------------------
  325|      0|    {
  326|       |      // Use the new type to create a new entry that is strongly typed.
  327|      0|      entry.info = TypeInfo::Create<T>();
  328|      0|      entry.sequence_id++;
  329|      0|      entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  330|      0|      previous_any = std::move(new_value);
  331|      0|      return;
  332|      0|    }
  333|       |
  334|      0|    std::type_index previous_type = entry.info.type();
  335|       |
  336|       |    // check type mismatch
  337|      0|    if(previous_type != std::type_index(typeid(T)) && previous_type != new_value.type())
  ------------------
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:8): [True: 0, False: 0]
  |  Branch (337:55): [True: 0, False: 0]
  ------------------
  338|      0|    {
  339|      0|      bool mismatching = true;
  340|      0|      if(std::is_constructible<StringView, T>::value)
  ------------------
  |  Branch (340:10): [True: 0, Folded]
  ------------------
  341|      0|      {
  342|      0|        Any any_from_string = entry.info.parseString(value);
  343|      0|        if(any_from_string.empty() == false)
  ------------------
  |  Branch (343:12): [True: 0, False: 0]
  ------------------
  344|      0|        {
  345|      0|          mismatching = false;
  346|      0|          new_value = std::move(any_from_string);
  347|      0|        }
  348|      0|      }
  349|       |      // check if we are doing a safe cast between numbers
  350|       |      // for instance, it is safe to use int(100) to set
  351|       |      // a uint8_t port, but not int(-42) or int(300)
  352|       |      if constexpr(std::is_arithmetic_v<T>)
  353|       |      {
  354|       |        if(mismatching && isCastingSafe(previous_type, value))
  355|       |        {
  356|       |          mismatching = false;
  357|       |        }
  358|       |      }
  359|       |
  360|      0|      if(mismatching)
  ------------------
  |  Branch (360:10): [True: 0, False: 0]
  ------------------
  361|      0|      {
  362|      0|        debugMessage();
  363|       |
  364|      0|        auto msg = StrCat("Blackboard::set(", key,
  365|      0|                          "): once declared, "
  366|      0|                          "the type of a port shall not change. "
  367|      0|                          "Previously declared type [",
  368|      0|                          BT::demangle(previous_type), "], current type [",
  369|      0|                          BT::demangle(typeid(T)), "]");
  370|      0|        throw LogicError(msg);
  371|      0|      }
  372|      0|    }
  373|       |    // if doing set<BT::Any>, skip type check
  374|       |    if constexpr(std::is_same_v<Any, T>)
  375|       |    {
  376|       |      previous_any = new_value;
  377|       |    }
  378|       |    else
  379|      0|    {
  380|       |      // copy only if the type is compatible
  381|      0|      new_value.copyInto(previous_any);
  382|      0|    }
  383|      0|    entry.sequence_id++;
  384|      0|    entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
  385|      0|  }
  386|  5.55k|}
_ZN2BT10Blackboard5EntryC2ERKNS_8TypeInfoE:
   61|  31.5k|    Entry(const TypeInfo& _info) : info(_info)
   62|  31.5k|    {}
_ZN2BT10Blackboard5EntryD2Ev:
   64|  31.5k|    ~Entry() = default;

_ZNK4linb3any4typeEv:
  176|  4.47M|    {
  177|  4.47M|        return empty()? typeid(void) : this->vtable->type();
  ------------------
  |  Branch (177:16): [True: 4, False: 4.47M]
  ------------------
  178|  4.47M|    }
_ZNK4linb3any5emptyEv:
  169|  18.7M|    {
  170|  18.7M|        return this->vtable == nullptr;
  171|  18.7M|    }
_ZN4linb3anyC2Ev:
   72|  95.0k|        vtable(nullptr)
   73|  95.0k|    {
   74|  95.0k|    }
_ZN4linb3anyD2Ev:
  100|  7.76M|    {
  101|  7.76M|        this->clear();
  102|  7.76M|    }
_ZN4linb3any5clearEv:
  159|  7.76M|    {
  160|  7.76M|        if(!empty())
  ------------------
  |  Branch (160:12): [True: 5.27M, False: 2.49M]
  ------------------
  161|  5.27M|        {
  162|  5.27M|            this->vtable->destroy(storage);
  163|  5.27M|            this->vtable = nullptr;
  164|  5.27M|        }
  165|  7.76M|    }
_ZN4linb8any_castIdEET_RKNS_3anyE:
  468|  14.2k|{
  469|  14.2k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|  14.2k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|  14.2k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 14.2k]
  ------------------
  472|  14.2k|#endif
  473|  14.2k|    return *p;
  474|  14.2k|}
_ZN4linb8any_castIKdEEPKT_PKNS_3anyE:
  510|  14.2k|{
  511|  14.2k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|  14.2k|#ifndef ANY_IMPL_NO_RTTI
  514|  14.2k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 14.2k, False: 0]
  |  Branch (514:20): [True: 14.2k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|  14.2k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|  14.2k|}
_ZNK4linb3any8is_typedERKSt9type_info:
  355|   737k|    {
  356|   737k|        return is_same(this->type(), t);
  357|   737k|    }
_ZN4linb3any7is_sameERKSt9type_infoS3_:
  368|   737k|    {
  369|       |#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
  370|       |        return &a == &b;
  371|       |#else
  372|   737k|        return a == b;
  373|   737k|#endif
  374|   737k|    }
_ZNK4linb3any4castIKdEEPKT_v:
  380|  14.2k|    {
  381|  14.2k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 14.2k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|  14.2k|            reinterpret_cast<const T*>(&storage.stack);
  384|  14.2k|    }
_ZN4linb8any_castIN7SafeAny12SimpleStringEEET_RKNS_3anyE:
  468|   454k|{
  469|   454k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|   454k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|   454k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 454k]
  ------------------
  472|   454k|#endif
  473|   454k|    return *p;
  474|   454k|}
_ZN4linb8any_castIKN7SafeAny12SimpleStringEEEPKT_PKNS_3anyE:
  510|   454k|{
  511|   454k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|   454k|#ifndef ANY_IMPL_NO_RTTI
  514|   454k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 454k, False: 0]
  |  Branch (514:20): [True: 454k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|   454k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|   454k|}
_ZNK4linb3any4castIKN7SafeAny12SimpleStringEEEPKT_v:
  380|   454k|    {
  381|   454k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 454k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|   454k|            reinterpret_cast<const T*>(&storage.stack);
  384|   454k|    }
_ZN4linb8any_castIlEET_RKNS_3anyE:
  468|   268k|{
  469|   268k|    auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
  470|   268k|#ifndef ANY_IMPL_NO_EXCEPTIONS
  471|   268k|    if(p == nullptr) throw bad_any_cast();
  ------------------
  |  Branch (471:8): [True: 0, False: 268k]
  ------------------
  472|   268k|#endif
  473|   268k|    return *p;
  474|   268k|}
_ZN4linb8any_castIKlEEPKT_PKNS_3anyE:
  510|   268k|{
  511|   268k|    using T = typename std::decay<ValueType>::type;
  512|       |
  513|   268k|#ifndef ANY_IMPL_NO_RTTI
  514|   268k|    if (operand && operand->is_typed(typeid(T)))
  ------------------
  |  Branch (514:9): [True: 268k, False: 0]
  |  Branch (514:20): [True: 268k, False: 0]
  ------------------
  515|       |#else
  516|       |    if (operand && operand->vtable == any::vtable_for_type<T>())
  517|       |#endif
  518|   268k|        return operand->cast<ValueType>();
  519|      0|    else
  520|      0|        return nullptr;
  521|   268k|}
_ZNK4linb3any4castIKlEEPKT_v:
  380|   268k|    {
  381|   268k|        return requires_allocation<typename std::decay<T>::type>::value?
  ------------------
  |  Branch (381:16): [Folded, False: 268k]
  ------------------
  382|      0|            reinterpret_cast<const T*>(storage.dynamic) :
  383|   268k|            reinterpret_cast<const T*>(&storage.stack);
  384|   268k|    }
_ZN4linb3anyC2IlvEEOT_:
  110|  1.80M|    {
  111|  1.80M|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|  1.80M|            "T shall satisfy the CopyConstructible requirements.");
  113|  1.80M|        this->construct(std::forward<ValueType>(value));
  114|  1.80M|    }
_ZN4linb3any9constructIlEEvOT_:
  439|  1.80M|    {
  440|  1.80M|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|  1.80M|        this->vtable = vtable_for_type<T>();
  443|       |
  444|  1.80M|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|  1.80M|    }
_ZN4linb3any15vtable_for_typeIlEEPNS0_11vtable_typeEv:
  333|  1.80M|    {
  334|  1.80M|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|  1.80M|        static vtable_type table = {
  336|  1.80M|#ifndef ANY_IMPL_NO_RTTI
  337|  1.80M|            VTableType::type,
  338|  1.80M|#endif
  339|  1.80M|            VTableType::destroy,
  340|  1.80M|            VTableType::copy, VTableType::move,
  341|  1.80M|            VTableType::swap,
  342|  1.80M|        };
  343|  1.80M|        return &table;
  344|  1.80M|    }
_ZN4linb3any12vtable_stackIlE4typeEv:
  289|  1.75M|        {
  290|  1.75M|            return typeid(T);
  291|  1.75M|        }
_ZN4linb3any12vtable_stackIlE7destroyERNS0_13storage_unionE:
  295|  6.05M|        {
  296|  6.05M|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|  6.05M|        }
_ZN4linb3any12vtable_stackIlE4copyERKNS0_13storage_unionERS3_:
  300|  2.07M|        {
  301|  2.07M|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|  2.07M|        }
_ZN4linb3any12vtable_stackIlE4moveERNS0_13storage_unionES4_:
  305|  2.18M|        {
  306|       |            // one of the conditions for using vtable_stack is a nothrow move constructor,
  307|       |            // so this move constructor will never throw a exception.
  308|  2.18M|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|  2.18M|            destroy(src);
  310|  2.18M|        }
_ZN4linb3any12vtable_stackIlE4swapERNS0_13storage_unionES4_:
  313|  26.3k|        {
  314|  26.3k|            storage_union tmp_storage;
  315|  26.3k|            move(rhs, tmp_storage);
  316|  26.3k|            move(lhs, rhs);
  317|  26.3k|            move(tmp_storage, lhs);
  318|  26.3k|        }
_ZN4linb3any12do_constructIllEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|  1.80M|    {
  432|  1.80M|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|  1.80M|    }
_ZN4linb3anyaSERKS0_:
  129|   270k|    {
  130|   270k|        any(rhs).swap(*this);
  131|   270k|        return *this;
  132|   270k|    }
_ZN4linb3anyC2ERKS0_:
   78|  2.82M|        vtable(rhs.vtable)
   79|  2.82M|    {
   80|  2.82M|        if(!rhs.empty())
  ------------------
  |  Branch (80:12): [True: 2.82M, False: 206]
  ------------------
   81|  2.82M|        {
   82|  2.82M|            rhs.vtable->copy(rhs.storage, this->storage);
   83|  2.82M|        }
   84|  2.82M|    }
_ZN4linb3any4swapERS0_:
  183|   311k|    {
  184|   311k|        if(this->vtable != rhs.vtable)
  ------------------
  |  Branch (184:12): [True: 234k, False: 77.7k]
  ------------------
  185|   234k|        {
  186|   234k|            any tmp(std::move(rhs));
  187|       |
  188|       |            // move from *this to rhs.
  189|   234k|            rhs.vtable = this->vtable;
  190|   234k|            if(this->vtable != nullptr)
  ------------------
  |  Branch (190:16): [True: 234k, False: 0]
  ------------------
  191|   234k|            {
  192|   234k|                this->vtable->move(this->storage, rhs.storage);
  193|       |                //this->vtable = nullptr; -- unneeded, see below
  194|   234k|            }
  195|       |
  196|       |            // move from tmp (previously rhs) to *this.
  197|   234k|            this->vtable = tmp.vtable;
  198|   234k|            if(tmp.vtable != nullptr)
  ------------------
  |  Branch (198:16): [True: 203k, False: 30.1k]
  ------------------
  199|   203k|            {
  200|   203k|                tmp.vtable->move(tmp.storage, this->storage);
  201|   203k|                tmp.vtable = nullptr;
  202|   203k|            }
  203|   234k|        }
  204|  77.7k|        else // same types
  205|  77.7k|        {
  206|  77.7k|            if(this->vtable != nullptr)
  ------------------
  |  Branch (206:16): [True: 46.1k, False: 31.5k]
  ------------------
  207|  46.1k|                this->vtable->swap(this->storage, rhs.storage);
  208|  77.7k|        }
  209|   311k|    }
_ZN4linb3anyC2EOS0_:
   89|  2.39M|        vtable(rhs.vtable)
   90|  2.39M|    {
   91|  2.39M|        if(!rhs.empty())
  ------------------
  |  Branch (91:12): [True: 2.36M, False: 30.1k]
  ------------------
   92|  2.36M|        {
   93|  2.36M|            rhs.vtable->move(rhs.storage, this->storage);
   94|  2.36M|            rhs.vtable = nullptr;
   95|  2.36M|        }
   96|  2.39M|    }
_ZN4linb3anyaSEOS0_:
  139|  39.7k|    {
  140|  39.7k|        std::move(rhs).swap(*this);
  141|  39.7k|        return *this;
  142|  39.7k|    }
_ZN4linb3anyaSIlvEERS0_OT_:
  150|    865|    {
  151|    865|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  152|    865|            "T shall satisfy the CopyConstructible requirements.");
  153|    865|        any(std::forward<ValueType>(value)).swap(*this);
  154|    865|        return *this;
  155|    865|    }
_ZN4linb3anyaSIdvEERS0_OT_:
  150|    194|    {
  151|    194|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  152|    194|            "T shall satisfy the CopyConstructible requirements.");
  153|    194|        any(std::forward<ValueType>(value)).swap(*this);
  154|    194|        return *this;
  155|    194|    }
_ZN4linb3anyC2IdvEEOT_:
  110|    194|    {
  111|    194|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|    194|            "T shall satisfy the CopyConstructible requirements.");
  113|    194|        this->construct(std::forward<ValueType>(value));
  114|    194|    }
_ZN4linb3any9constructIdEEvOT_:
  439|    194|    {
  440|    194|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|    194|        this->vtable = vtable_for_type<T>();
  443|       |
  444|    194|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|    194|    }
_ZN4linb3any15vtable_for_typeIdEEPNS0_11vtable_typeEv:
  333|   267k|    {
  334|   267k|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|   267k|        static vtable_type table = {
  336|   267k|#ifndef ANY_IMPL_NO_RTTI
  337|   267k|            VTableType::type,
  338|   267k|#endif
  339|   267k|            VTableType::destroy,
  340|   267k|            VTableType::copy, VTableType::move,
  341|   267k|            VTableType::swap,
  342|   267k|        };
  343|   267k|        return &table;
  344|   267k|    }
_ZN4linb3any12vtable_stackIdE4typeEv:
  289|  92.3k|        {
  290|  92.3k|            return typeid(T);
  291|  92.3k|        }
_ZN4linb3any12vtable_stackIdE7destroyERNS0_13storage_unionE:
  295|   314k|        {
  296|   314k|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|   314k|        }
_ZN4linb3any12vtable_stackIdE4copyERKNS0_13storage_unionERS3_:
  300|  20.7k|        {
  301|  20.7k|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|  20.7k|        }
_ZN4linb3any12vtable_stackIdE4moveERNS0_13storage_unionES4_:
  305|  26.2k|        {
  306|       |            // one of the conditions for using vtable_stack is a nothrow move constructor,
  307|       |            // so this move constructor will never throw a exception.
  308|  26.2k|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|  26.2k|            destroy(src);
  310|  26.2k|        }
_ZN4linb3any12vtable_stackIdE4swapERNS0_13storage_unionES4_:
  313|  3.12k|        {
  314|  3.12k|            storage_union tmp_storage;
  315|  3.12k|            move(rhs, tmp_storage);
  316|  3.12k|            move(lhs, rhs);
  317|  3.12k|            move(tmp_storage, lhs);
  318|  3.12k|        }
_ZN4linb3any12do_constructIddEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|    194|    {
  432|    194|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|    194|    }
_ZN4linb3anyC2IRKdvEEOT_:
  110|   267k|    {
  111|   267k|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|   267k|            "T shall satisfy the CopyConstructible requirements.");
  113|   267k|        this->construct(std::forward<ValueType>(value));
  114|   267k|    }
_ZN4linb3any9constructIRKdEEvOT_:
  439|   267k|    {
  440|   267k|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|   267k|        this->vtable = vtable_for_type<T>();
  443|       |
  444|   267k|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|   267k|    }
_ZN4linb3any12do_constructIRKddEENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|   267k|    {
  432|   267k|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|   267k|    }
_ZN4linb3anyC2IN7SafeAny12SimpleStringEvEEOT_:
  110|   382k|    {
  111|   382k|        static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
  112|   382k|            "T shall satisfy the CopyConstructible requirements.");
  113|   382k|        this->construct(std::forward<ValueType>(value));
  114|   382k|    }
_ZN4linb3any9constructIN7SafeAny12SimpleStringEEEvOT_:
  439|   382k|    {
  440|   382k|        using T = typename std::decay<ValueType>::type;
  441|       |
  442|   382k|        this->vtable = vtable_for_type<T>();
  443|       |
  444|   382k|        do_construct<ValueType,T>(std::forward<ValueType>(value));
  445|   382k|    }
_ZN4linb3any15vtable_for_typeIN7SafeAny12SimpleStringEEEPNS0_11vtable_typeEv:
  333|   382k|    {
  334|   382k|        using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
  335|   382k|        static vtable_type table = {
  336|   382k|#ifndef ANY_IMPL_NO_RTTI
  337|   382k|            VTableType::type,
  338|   382k|#endif
  339|   382k|            VTableType::destroy,
  340|   382k|            VTableType::copy, VTableType::move,
  341|   382k|            VTableType::swap,
  342|   382k|        };
  343|   382k|        return &table;
  344|   382k|    }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4typeEv:
  289|  2.62M|        {
  290|  2.62M|            return typeid(T);
  291|  2.62M|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE7destroyERNS0_13storage_unionE:
  295|  1.84M|        {
  296|  1.84M|            reinterpret_cast<T*>(&storage.stack)->~T();
  297|  1.84M|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4copyERKNS0_13storage_unionERS5_:
  300|   731k|        {
  301|   731k|            new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
  302|   731k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4moveERNS0_13storage_unionES6_:
  305|   730k|        {
  306|       |            // one of the conditions for using vtable_stack is a nothrow move constructor,
  307|       |            // so this move constructor will never throw a exception.
  308|   730k|            new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
  309|   730k|            destroy(src);
  310|   730k|        }
_ZN4linb3any12vtable_stackIN7SafeAny12SimpleStringEE4swapERNS0_13storage_unionES6_:
  313|  16.7k|        {
  314|  16.7k|            storage_union tmp_storage;
  315|  16.7k|            move(rhs, tmp_storage);
  316|  16.7k|            move(lhs, rhs);
  317|  16.7k|            move(tmp_storage, lhs);
  318|  16.7k|        }
_ZN4linb3any12do_constructIN7SafeAny12SimpleStringES3_EENSt9enable_ifIXntsr19requires_allocationIT0_EE5valueEvE4typeEOT_:
  431|   382k|    {
  432|   382k|        new (&storage.stack) T(std::forward<ValueType>(value));
  433|   382k|    }

_ZNK6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  5.55k|    {
 2192|  5.55k|        return has_value();
 2193|  5.55k|    }
_ZNK6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  11.1k|    {
 2197|  11.1k|        return contained.has_value();
 2198|  11.1k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  11.1k|    {
  787|  11.1k|        return m_has_value;
  788|  11.1k|    }
_ZNK6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  7.10k|    {
 2192|  7.10k|        return has_value();
 2193|  7.10k|    }
_ZNK6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  18.2k|    {
 2197|  18.2k|        return contained.has_value();
 2198|  18.2k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  18.2k|    {
  787|  18.2k|        return m_has_value;
  788|  18.2k|    }
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IdTnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIdOT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISB_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SG_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESG_EE5valuesr3std14is_convertibleISC_dEE5valueEiE4typeELi0EEESC_:
 1927|   744k|    : contained( true )
 1928|   744k|    {
 1929|   744k|        contained.construct_value( std::forward<U>( value ) );
 1930|   744k|    }
_ZN6nonstd13expected_lite6detail9storage_tIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|   950k|        : storage_t_impl<T, E>( has_value )
  922|   950k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|   950k|        : m_has_value( has_value )
  674|   950k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOd:
  687|   744k|    {
  688|   744k|        new( &m_value ) value_type( std::move( e ) );
  689|   744k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRA39_KcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS7_:
 1566|    166|{
 1567|    166|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|    166|}
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IRA39_S2_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS9_E4typeESt10in_place_tEE5valuentsr3std7is_sameISD_S4_EE5valueEiE4typeELi0EEEOS9_:
 1237|    166|    : m_error( std::forward<E2>( error ) )
 1238|    166|    {}
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS7_OT_EE5valuesr3std14is_convertibleISE_S7_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISD_EE:
 1977|    166|    : contained( false )
 1978|    166|    {
 1979|    166|        contained.construct_error( std::move( error.error() ) );
 1980|    166|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOS8_:
  714|    332|    {
  715|    332|        new( &m_error ) error_type( std::move( e ) );
  716|    332|    }
_ZNR6nonstd13expected_lite15unexpected_typeIPKcE5errorEv:
 1334|  5.79k|    {
 1335|  5.79k|        return m_error;
 1336|  5.79k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|   950k|    ~storage_t_impl() {}
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IRdTnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIdOT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISC_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SH_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESH_EE5valuesr3std14is_convertibleISD_dEE5valueEiE4typeELi0EEESD_:
 1927|   205k|    : contained( true )
 1928|   205k|    {
 1929|   205k|        contained.construct_value( std::forward<U>( value ) );
 1930|   205k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueERKd:
  682|   205k|    {
  683|   205k|        new( &m_value ) value_type( e );
  684|   205k|    }
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2EOS8_:
 1793|    166|    nsel_constexpr14 expected( expected &&      ) = default;
_ZN6nonstd13expected_lite6detail9storage_tIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2EOS9_:
  932|    166|        : storage_t_impl<T, E>( other.has_value() )
  933|    166|    {
  934|    166|        if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
  ------------------
  |  Branch (934:14): [True: 0, False: 166]
  ------------------
  935|    166|        else                     this->construct_error( std::move( other.error() ) );
  936|    166|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  2.85M|    {
  787|  2.85M|        return m_has_value;
  788|  2.85M|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|   950k|    {
  742|   950k|        return m_value;
  743|   950k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
  771|    332|    {
  772|    332|        return m_error;
  773|    332|    }
_ZNR6nonstd13expected_lite15unexpected_typeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
 1334|  1.55k|    {
 1335|  1.55k|        return m_error;
 1336|  1.55k|    }
_ZNK6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|   950k|    {
 2192|   950k|        return has_value();
 2193|   950k|    }
_ZNK6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  2.85M|    {
 2197|  2.85M|        return contained.has_value();
 2198|  2.85M|    }
_ZNR6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|   950k|    {
 2211|   950k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 950k, False: 0]
  ------------------
 2212|   950k|            ? ( contained.value() )
 2213|   950k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|   950k|    }
_ZNR6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
 2241|    166|    {
 2242|       |        return assert( ! has_value() ), contained.error();
 2243|    166|    }
_ZN6nonstd13expected_lite8expectedIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|   950k|    {
 2038|   950k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 950k, False: 332]
  ------------------
 2039|    332|        else               contained.destruct_error();
 2040|   950k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|   950k|    {
  705|   950k|        m_value.~value_type();
  706|   950k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIdNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|    332|    {
  732|    332|        m_error.~error_type();
  733|    332|    }
_ZN6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IlTnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIlOT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISB_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SG_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESG_EE5valuesr3std14is_convertibleISC_lEE5valueEiE4typeELi0EEESC_:
 1927|  5.00k|    : contained( true )
 1928|  5.00k|    {
 1929|  5.00k|        contained.construct_value( std::forward<U>( value ) );
 1930|  5.00k|    }
_ZN6nonstd13expected_lite6detail9storage_tIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  5.00k|        : storage_t_impl<T, E>( has_value )
  922|  5.00k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  5.00k|        : m_has_value( has_value )
  674|  5.00k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOl:
  687|  5.00k|    {
  688|  5.00k|        new( &m_value ) value_type( std::move( e ) );
  689|  5.00k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  5.00k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  15.0k|    {
  787|  15.0k|        return m_has_value;
  788|  15.0k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  5.00k|    {
  742|  5.00k|        return m_value;
  743|  5.00k|    }
_ZNK6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  5.00k|    {
 2192|  5.00k|        return has_value();
 2193|  5.00k|    }
_ZNK6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  15.0k|    {
 2197|  15.0k|        return contained.has_value();
 2198|  15.0k|    }
_ZNR6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  5.00k|    {
 2211|  5.00k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 5.00k, False: 0]
  ------------------
 2212|  5.00k|            ? ( contained.value() )
 2213|  5.00k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  5.00k|    }
_ZN6nonstd13expected_lite8expectedIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  5.00k|    {
 2038|  5.00k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 5.00k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  5.00k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIlNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  5.00k|    {
  705|  5.00k|        m_value.~value_type();
  706|  5.00k|    }
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  5.55k|    {
 2038|  5.55k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 3.99k, False: 1.55k]
  ------------------
 2039|  1.55k|        else               contained.destruct_error();
 2040|  5.55k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  3.99k|    {
  705|  3.99k|        m_value.~value_type();
  706|  3.99k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  1.55k|    {
  732|  1.55k|        m_error.~error_type();
  733|  1.55k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  5.55k|    ~storage_t_impl() {}
_ZN6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  7.10k|    {
 2038|  7.10k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 3.99k, False: 3.10k]
  ------------------
 2039|  3.10k|        else               contained.destruct_error();
 2040|  7.10k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  3.99k|    {
  705|  3.99k|        m_value.~value_type();
  706|  3.99k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  3.10k|    {
  732|  3.10k|        m_error.~error_type();
  733|  3.10k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  7.10k|    ~storage_t_impl() {}
_ZNR6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  3.99k|    {
 2211|  3.99k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 3.99k, False: 0]
  ------------------
 2212|  3.99k|            ? ( contained.value() )
 2213|  3.99k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  3.99k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  3.99k|    {
  742|  3.99k|        return m_value;
  743|  3.99k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
  771|  1.55k|    {
  772|  1.55k|        return m_error;
  773|  1.55k|    }
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IS3_TnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIS3_OT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISD_E4typeESt10in_place_tEE5valuentsr3std7is_sameISA_SI_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS9_EESI_EE5valuesr3std14is_convertibleISE_S3_EE5valueEiE4typeELi0EEESE_:
 1927|  2.81k|    : contained( true )
 1928|  2.81k|    {
 1929|  2.81k|        contained.construct_value( std::forward<U>( value ) );
 1930|  2.81k|    }
_ZN6nonstd13expected_lite6detail9storage_tIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  5.33k|        : storage_t_impl<T, E>( has_value )
  922|  5.33k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  5.33k|        : m_has_value( has_value )
  674|  5.33k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOS4_:
  687|  2.81k|    {
  688|  2.81k|        new( &m_value ) value_type( std::move( e ) );
  689|  2.81k|    }
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IS9_TnNSt9enable_ifIXaasr3std16is_constructibleIS9_OT_EE5valuesr3std14is_convertibleISE_S9_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISD_EE:
 1977|  1.55k|    : contained( false )
 1978|  1.55k|    {
 1979|  1.55k|        contained.construct_error( std::move( error.error() ) );
 1980|  1.55k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOSA_:
  714|  2.52k|    {
  715|  2.52k|        new( &m_error ) error_type( std::move( e ) );
  716|  2.52k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  5.33k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  5.33k|    {
  787|  5.33k|        return m_has_value;
  788|  5.33k|    }
_ZNK6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  5.33k|    {
 2197|  5.33k|        return contained.has_value();
 2198|  5.33k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOSB_:
 1566|  1.55k|{
 1567|  1.55k|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|  1.55k|}
_ZN6nonstd13expected_lite15unexpected_typeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IRS7_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS7_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISC_E4typeESt10in_place_tEE5valuentsr3std7is_sameISG_S8_EE5valueEiE4typeELi0EEEOSC_:
 1237|  1.55k|    : m_error( std::forward<E2>( error ) )
 1238|  1.55k|    {}
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  5.33k|    {
 2038|  5.33k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 2.81k, False: 2.52k]
  ------------------
 2039|  2.52k|        else               contained.destruct_error();
 2040|  5.33k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  2.81k|    {
  705|  2.81k|        m_value.~value_type();
  706|  2.81k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_errorEv:
  731|  2.52k|    {
  732|  2.52k|        m_error.~error_type();
  733|  2.52k|    }
_ZNK6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_E9has_valueEv:
 2196|  1.40M|    {
 2197|  1.40M|        return contained.has_value();
 2198|  1.40M|    }
_ZNK6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_EcvbEv:
 2191|   469k|    {
 2192|   469k|        return has_value();
 2193|   469k|    }
_ZNK6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E9has_valueEv:
  786|  1.40M|    {
  787|  1.40M|        return m_has_value;
  788|  1.40M|    }
_ZN6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_EC2IS7_TnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIS7_OT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISB_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SG_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESG_EE5valuesr3std14is_convertibleISC_S7_EE5valueEiE4typeELi0EEESC_:
 1927|   469k|    : contained( true )
 1928|   469k|    {
 1929|   469k|        contained.construct_value( std::forward<U>( value ) );
 1930|   469k|    }
_ZN6nonstd13expected_lite6detail9storage_tINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_Lb1ELb1EEC2Eb:
  921|   469k|        : storage_t_impl<T, E>( has_value )
  922|   469k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_EC2Eb:
  673|   469k|        : m_has_value( has_value )
  674|   469k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E15construct_valueEOS8_:
  687|   469k|    {
  688|   469k|        new( &m_value ) value_type( std::move( e ) );
  689|   469k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_ED2Ev:
  670|   469k|    ~storage_t_impl() {}
_ZN6nonstd13expected_lite15make_unexpectedIPKcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS6_:
 1566|  5.54k|{
 1567|  5.54k|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|  5.54k|}
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEv:
  677|  3.99k|    {
  678|  3.99k|        new( &m_value ) value_type();
  679|  3.99k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOS9_:
  714|  1.55k|    {
  715|  1.55k|        new( &m_error ) error_type( std::move( e ) );
  716|  1.55k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E5valueEv:
  741|   469k|    {
  742|   469k|        return m_value;
  743|   469k|    }
_ZNR6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_E5valueEv:
 2210|   469k|    {
 2211|   469k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 469k, False: 0]
  ------------------
 2212|   469k|            ? ( contained.value() )
 2213|   469k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|   469k|    }
_ZN6nonstd13expected_lite8expectedINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_ED2Ev:
 2037|   469k|    {
 2038|   469k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 469k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|   469k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_E14destruct_valueEv:
  704|   469k|    {
  705|   469k|        m_value.~value_type();
  706|   469k|    }
_ZN6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IS3_TnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIS3_OT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISD_E4typeESt10in_place_tEE5valuentsr3std7is_sameISA_SI_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS9_EESI_EE5valuesr3std14is_convertibleISE_S3_EE5valueEiE4typeELi0EEESE_:
 1927|  17.3k|    : contained( true )
 1928|  17.3k|    {
 1929|  17.3k|        contained.construct_value( std::forward<U>( value ) );
 1930|  17.3k|    }
_ZN6nonstd13expected_lite6detail9storage_tIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  17.3k|        : storage_t_impl<T, E>( has_value )
  922|  17.3k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  17.3k|        : m_has_value( has_value )
  674|  17.3k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOS4_:
  687|  17.3k|    {
  688|  17.3k|        new( &m_value ) value_type( std::move( e ) );
  689|  17.3k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  17.3k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  51.9k|    {
  787|  51.9k|        return m_has_value;
  788|  51.9k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  17.3k|    {
  742|  17.3k|        return m_value;
  743|  17.3k|    }
_ZNK6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  17.3k|    {
 2192|  17.3k|        return has_value();
 2193|  17.3k|    }
_ZNK6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  51.9k|    {
 2197|  51.9k|        return contained.has_value();
 2198|  51.9k|    }
_ZNR6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  17.3k|    {
 2211|  17.3k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 17.3k, False: 0]
  ------------------
 2212|  17.3k|            ? ( contained.value() )
 2213|  17.3k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  17.3k|    }
_ZN6nonstd13expected_lite8expectedIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  17.3k|    {
 2038|  17.3k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 17.3k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  17.3k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIN7SafeAny12SimpleStringENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  17.3k|    {
  705|  17.3k|        m_value.~value_type();
  706|  17.3k|    }
_ZN6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IbTnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIbOT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISB_E4typeESt10in_place_tEE5valuentsr3std7is_sameIS8_SG_EE5valuentsr3std7is_sameINS0_15unexpected_typeIS7_EESG_EE5valuesr3std14is_convertibleISC_bEE5valueEiE4typeELi0EEESC_:
 1927|  4.70k|    : contained( true )
 1928|  4.70k|    {
 1929|  4.70k|        contained.construct_value( std::forward<U>( value ) );
 1930|  4.70k|    }
_ZN6nonstd13expected_lite6detail9storage_tIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  4.70k|        : storage_t_impl<T, E>( has_value )
  922|  4.70k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  4.70k|        : m_has_value( has_value )
  674|  4.70k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOb:
  687|  4.70k|    {
  688|  4.70k|        new( &m_value ) value_type( std::move( e ) );
  689|  4.70k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
  670|  4.70k|    ~storage_t_impl() {}
_ZNK6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
  786|  14.1k|    {
  787|  14.1k|        return m_has_value;
  788|  14.1k|    }
_ZNR6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
  741|  4.70k|    {
  742|  4.70k|        return m_value;
  743|  4.70k|    }
_ZNK6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEcvbEv:
 2191|  4.70k|    {
 2192|  4.70k|        return has_value();
 2193|  4.70k|    }
_ZNK6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE9has_valueEv:
 2196|  14.1k|    {
 2197|  14.1k|        return contained.has_value();
 2198|  14.1k|    }
_ZNR6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5valueEv:
 2210|  4.70k|    {
 2211|  4.70k|        return has_value()
  ------------------
  |  Branch (2211:16): [True: 4.70k, False: 0]
  ------------------
 2212|  4.70k|            ? ( contained.value() )
 2213|  4.70k|            : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
 2214|  4.70k|    }
_ZN6nonstd13expected_lite8expectedIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEED2Ev:
 2037|  4.70k|    {
 2038|  4.70k|        if ( has_value() ) contained.destruct_value();
  ------------------
  |  Branch (2038:14): [True: 4.70k, False: 0]
  ------------------
 2039|      0|        else               contained.destruct_error();
 2040|  4.70k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implIbNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE14destruct_valueEv:
  704|  4.70k|    {
  705|  4.70k|        m_value.~value_type();
  706|  4.70k|    }
_ZN6nonstd13expected_lite15make_unexpectedIRA13_KcEENS0_15unexpected_typeINSt5decayIT_E4typeEEEOS7_:
 1566|     84|{
 1567|     84|    return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
 1568|     84|}
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IRA13_S2_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS9_E4typeESt10in_place_tEE5valuentsr3std7is_sameISD_S4_EE5valueEiE4typeELi0EEEOS9_:
 1237|     84|    : m_error( std::forward<E2>( error ) )
 1238|     84|    {}
_ZN6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleISF_OT_EE5valuesr3std14is_convertibleISM_SF_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISL_EE:
 1977|  3.10k|    : contained( false )
 1978|  3.10k|    {
 1979|  3.10k|        contained.construct_error( std::move( error.error() ) );
 1980|  3.10k|    }
_ZN6nonstd13expected_lite6detail9storage_tISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  7.10k|        : storage_t_impl<T, E>( has_value )
  922|  7.10k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  7.10k|        : m_has_value( has_value )
  674|  7.10k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_errorEOSG_:
  714|  3.10k|    {
  715|  3.10k|        new( &m_error ) error_type( std::move( e ) );
  716|  3.10k|    }
script_parser.cpp:_ZN6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IZNS3_11ParseScriptERKSF_E3$_0TnNSt9enable_ifIXaaaaaaaasr3std16is_constructibleIS9_OT_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefISM_E4typeESt10in_place_tEE5valuentsr3std7is_sameISG_SR_EE5valuentsr3std7is_sameINS0_15unexpected_typeISF_EESR_EE5valuesr3std14is_convertibleISN_S9_EE5valueEiE4typeELi0EEESN_:
 1927|  3.99k|    : contained( true )
 1928|  3.99k|    {
 1929|  3.99k|        contained.construct_value( std::forward<U>( value ) );
 1930|  3.99k|    }
_ZN6nonstd13expected_lite6detail14storage_t_implISt8functionIFN2BT3AnyERNS4_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE15construct_valueEOSA_:
  687|  3.99k|    {
  688|  3.99k|        new( &m_value ) value_type( std::move( e ) );
  689|  3.99k|    }
_ZN6nonstd13expected_lite15unexpected_typeIPKcEC2IS3_TnNSt9enable_ifIXaaaasr3std16is_constructibleIS3_T_EE5valuentsr3std7is_sameINS0_5std2012remove_cvrefIS7_E4typeESt10in_place_tEE5valuentsr3std7is_sameISB_S4_EE5valueEiE4typeELi0EEEOS7_:
 1237|  5.54k|    : m_error( std::forward<E2>( error ) )
 1238|  5.54k|    {}
_ZN6nonstd13expected_lite8expectedIN2BT3AnyENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS9_OT_EE5valuesr3std14is_convertibleISG_S9_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISF_EE:
 1977|    975|    : contained( false )
 1978|    975|    {
 1979|    975|        contained.construct_error( std::move( error.error() ) );
 1980|    975|    }
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2IPKcTnNSt9enable_ifIXaasr3std16is_constructibleIS8_OT_EE5valuesr3std14is_convertibleISF_S8_EE5valueEiE4typeELi0EEEONS0_15unexpected_typeISE_EE:
 1977|  1.55k|    : contained( false )
 1978|  1.55k|    {
 1979|  1.55k|        contained.construct_error( std::move( error.error() ) );
 1980|  1.55k|    }
_ZN6nonstd13expected_lite6detail9storage_tISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEELb1ELb1EEC2Eb:
  921|  5.55k|        : storage_t_impl<T, E>( has_value )
  922|  5.55k|    {}
_ZN6nonstd13expected_lite6detail14storage_t_implISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2Eb:
  673|  5.55k|        : m_has_value( has_value )
  674|  5.55k|    {}
_ZN6nonstd13expected_lite8expectedISt9monostateNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEC2ILb1ETnNSt9enable_ifIXT_EiE4typeELi0EEEv:
 1787|  3.99k|    : contained( true )
 1788|  3.99k|    {
 1789|  3.99k|        contained.construct_value();
 1790|  3.99k|    }
_ZNR6nonstd13expected_lite8expectedISt8functionIFN2BT3AnyERNS3_3Ast11EnvironmentEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE5errorEv:
 2241|  1.55k|    {
 2242|       |        return assert( ! has_value() ), contained.error();
 2243|  1.55k|    }

_ZN2BT21BehaviorTreeExceptionC2IJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEDpRKT_:
   33|  6.29k|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|  6.29k|  {}
_ZNK2BT21BehaviorTreeException4whatEv:
   37|  6.52k|  {
   38|  6.52k|    return message_.c_str();
   39|  6.52k|  }
_ZN2BT12RuntimeErrorC2IJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEEDpRKT_:
   67|  6.29k|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|  6.29k|  {}
_ZN2BT12RuntimeErrorC2IJA42_cEEEDpRKT_:
   67|      2|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      2|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA42_cEEEDpRKT_:
   33|      2|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      2|  {}
_ZN2BT12RuntimeErrorC2IJA33_cEEEDpRKT_:
   67|      2|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      2|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA33_cEEEDpRKT_:
   33|      2|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      2|  {}
_ZN2BT12RuntimeErrorC2IJA31_cEEEDpRKT_:
   67|      1|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      1|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA31_cEEEDpRKT_:
   33|      1|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      1|  {}
_ZN2BT12RuntimeErrorC2IJA47_cEEEDpRKT_:
   67|     33|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|     33|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA47_cEEEDpRKT_:
   33|     33|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|     33|  {}
_ZN2BT12RuntimeErrorC2IJA63_cEEEDpRKT_:
   67|      7|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      7|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA63_cEEEDpRKT_:
   33|      7|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      7|  {}
_ZN2BT12RuntimeErrorC2IJA35_cEEEDpRKT_:
   67|      5|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      5|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA35_cEEEDpRKT_:
   33|      5|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      5|  {}
_ZN2BT12RuntimeErrorC2IJA74_cEEEDpRKT_:
   67|      6|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|      6|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA74_cEEEDpRKT_:
   33|      6|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|      6|  {}
_ZN2BT12RuntimeErrorC2IJA79_cEEEDpRKT_:
   67|    143|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|    143|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA79_cEEEDpRKT_:
   33|    143|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|    143|  {}
_ZN2BT12RuntimeErrorC2IJA24_cEEEDpRKT_:
   67|     26|  RuntimeError(const SV&... args) : BehaviorTreeException(args...)
   68|     26|  {}
_ZN2BT21BehaviorTreeExceptionC2IJA24_cEEEDpRKT_:
   33|     26|  BehaviorTreeException(const SV&... args) : message_(StrCat(args...))
   34|     26|  {}

_ZN2BT3Ast19ExprUnaryArithmeticC2ENS1_4op_tESt10shared_ptrINS0_8ExprBaseEE:
  118|  12.5k|  explicit ExprUnaryArithmetic(op_t op, expr_ptr e) : op(op), rhs(std::move(e))
  119|  12.5k|  {}
_ZN2BT3Ast8ExprBaseD2Ev:
   57|  10.3M|  virtual ~ExprBase() = default;
_ZNK2BT3Ast19ExprUnaryArithmetic8evaluateERNS0_11EnvironmentE:
  122|  2.66k|  {
  123|  2.66k|    auto rhs_v = rhs->evaluate(env);
  124|  2.66k|    if(rhs_v.isNumber())
  ------------------
  |  Branch (124:8): [True: 2.63k, False: 31]
  ------------------
  125|  2.63k|    {
  126|  2.63k|      const double rv = rhs_v.cast<double>();
  127|  2.63k|      switch(op)
  ------------------
  |  Branch (127:14): [True: 2.61k, False: 11]
  ------------------
  128|  2.63k|      {
  129|    888|        case negate:
  ------------------
  |  Branch (129:9): [True: 888, False: 1.74k]
  ------------------
  130|    888|          return Any(-rv);
  131|    811|        case complement:
  ------------------
  |  Branch (131:9): [True: 811, False: 1.81k]
  ------------------
  132|    811|          if(rv > static_cast<double>(std::numeric_limits<int64_t>::max()) ||
  ------------------
  |  Branch (132:14): [True: 1, False: 810]
  ------------------
  133|    810|             rv < static_cast<double>(std::numeric_limits<int64_t>::min()))
  ------------------
  |  Branch (133:14): [True: 1, False: 809]
  ------------------
  134|      2|          {
  135|      2|            throw RuntimeError("Number out of range for bitwise operation");
  136|      2|          }
  137|    809|          return Any(static_cast<double>(~static_cast<int64_t>(rv)));
  138|    920|        case logical_not:
  ------------------
  |  Branch (138:9): [True: 920, False: 1.71k]
  ------------------
  139|    920|          return Any(static_cast<double>(!static_cast<bool>(rv)));
  140|  2.63k|      }
  141|  2.63k|    }
  142|     31|    else if(rhs_v.isString())
  ------------------
  |  Branch (142:13): [True: 2, False: 29]
  ------------------
  143|      2|    {
  144|      2|      throw RuntimeError("Invalid operator for std::string");
  145|      2|    }
  146|     29|    throw RuntimeError("ExprUnaryArithmetic: undefined");
  147|  2.66k|  }
_ZN2BT3Ast11ExprLiteralC2ENS_3AnyE:
   71|  2.15M|  ExprLiteral(Any v) : value(v)
   72|  2.15M|  {}
_ZNK2BT3Ast11ExprLiteral8evaluateERNS0_11EnvironmentE:
   75|   260k|  {
   76|   260k|    return value;
   77|   260k|  }
_ZN2BT3Ast8ExprNameC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   84|  8.09M|  explicit ExprName(std::string n) : name(std::move(n))
   85|  8.09M|  {}
_ZNK2BT3Ast8ExprName8evaluateERNS0_11EnvironmentE:
   88|   108k|  {
   89|       |    //search first in the enums table
   90|   108k|    if(env.enums)
  ------------------
  |  Branch (90:8): [True: 108k, False: 0]
  ------------------
   91|   108k|    {
   92|   108k|      auto enum_ptr = env.enums->find(name);
   93|   108k|      if(enum_ptr != env.enums->end())
  ------------------
  |  Branch (93:10): [True: 0, False: 108k]
  ------------------
   94|      0|      {
   95|      0|        return Any(double(enum_ptr->second));
   96|      0|      }
   97|   108k|    }
   98|       |    // search now in the variables table
   99|   108k|    auto any_ref = env.vars->getAnyLocked(name);
  100|   108k|    if(!any_ref)
  ------------------
  |  Branch (100:8): [True: 564, False: 107k]
  ------------------
  101|    564|    {
  102|    564|      throw RuntimeError(StrCat("Variable not found: ", name));
  103|    564|    }
  104|   107k|    return *any_ref.get();
  105|   108k|  }
_ZN2BT3Ast14ExprAssignmentC2ESt10shared_ptrINS0_8ExprBaseEENS1_4op_tES4_:
  507|  55.3k|    : op(op), lhs(std::move(_lhs)), rhs(std::move(_rhs))
  508|  55.3k|  {}
_ZNK2BT3Ast14ExprAssignment8evaluateERNS0_11EnvironmentE:
  511|  20.8k|  {
  512|  20.8k|    auto varname = dynamic_cast<ExprName*>(lhs.get());
  513|  20.8k|    if(!varname)
  ------------------
  |  Branch (513:8): [True: 33, False: 20.8k]
  ------------------
  514|     33|    {
  515|     33|      throw RuntimeError("Assignment left operand not a blackboard entry");
  516|     33|    }
  517|  20.8k|    const auto& key = varname->name;
  518|       |
  519|  20.8k|    auto entry = env.vars->getEntry(key);
  520|  20.8k|    if(!entry)
  ------------------
  |  Branch (520:8): [True: 9.44k, False: 11.4k]
  ------------------
  521|  9.44k|    {
  522|       |      // variable doesn't exist, create it if using operator assign_create
  523|  9.44k|      if(op == assign_create)
  ------------------
  |  Branch (523:10): [True: 9.39k, False: 55]
  ------------------
  524|  9.39k|      {
  525|  9.39k|        env.vars->createEntry(key, PortInfo());
  526|  9.39k|        entry = env.vars->getEntry(key);
  527|  9.39k|        if(!entry)
  ------------------
  |  Branch (527:12): [True: 0, False: 9.39k]
  ------------------
  528|      0|        {
  529|      0|          throw LogicError("Bug: report");
  530|      0|        }
  531|  9.39k|      }
  532|     55|      else
  533|     55|      {
  534|       |        // fail otherwise
  535|     55|        auto msg = StrCat("The blackboard entry [", key,
  536|     55|                          "] doesn't exist, yet.\n"
  537|     55|                          "If you want to create a new one, "
  538|     55|                          "use the operator "
  539|     55|                          "[:=] instead of [=]");
  540|     55|        throw RuntimeError(msg);
  541|     55|      }
  542|  9.44k|    }
  543|  20.8k|    auto value = rhs->evaluate(env);
  544|       |
  545|  20.8k|    std::scoped_lock lock(entry->entry_mutex);
  546|  20.8k|    auto* dst_ptr = &entry->value;
  547|       |
  548|  20.8k|    auto errorPrefix = [dst_ptr, &key]() {
  549|  20.8k|      return StrCat("Error assigning a value to entry [", key, "] with type [",
  550|  20.8k|                    BT::demangle(dst_ptr->type()), "]. ");
  551|  20.8k|    };
  552|       |
  553|  20.8k|    if(value.empty())
  ------------------
  |  Branch (553:8): [True: 45, False: 20.7k]
  ------------------
  554|     45|    {
  555|     45|      throw RuntimeError(ErrorNotInit("right", opStr()));
  556|     45|    }
  557|       |
  558|  20.7k|    if(op == assign_create || op == assign_existing)
  ------------------
  |  Branch (558:8): [True: 11.4k, False: 9.26k]
  |  Branch (558:31): [True: 1.72k, False: 7.53k]
  ------------------
  559|  10.3k|    {
  560|       |      // the very fist assignment can come from any type.
  561|       |      // In the future, type check will be done by Any::copyInto
  562|  10.3k|      if(dst_ptr->empty() && entry->info.type() == typeid(AnyTypeAllowed))
  ------------------
  |  Branch (562:10): [True: 7.95k, False: 2.39k]
  |  Branch (562:10): [True: 7.95k, False: 2.39k]
  |  Branch (562:30): [True: 7.95k, False: 0]
  ------------------
  563|  7.95k|      {
  564|  7.95k|        *dst_ptr = value;
  565|  7.95k|      }
  566|  2.39k|      else if(value.isString() && !dst_ptr->isString())
  ------------------
  |  Branch (566:15): [True: 1.51k, False: 881]
  |  Branch (566:35): [True: 647, False: 863]
  ------------------
  567|    647|      {
  568|       |        // special case: string to other type.
  569|       |        // Check if we can use the StringConverter
  570|    647|        auto const str = value.cast<std::string>();
  571|    647|        const auto* entry_info = env.vars->entryInfo(key);
  572|       |
  573|    647|        if(auto converter = entry_info->converter())
  ------------------
  |  Branch (573:17): [True: 0, False: 647]
  ------------------
  574|      0|        {
  575|      0|          *dst_ptr = converter(str);
  576|      0|        }
  577|    647|        else if(dst_ptr->isNumber())
  ------------------
  |  Branch (577:17): [True: 647, False: 0]
  ------------------
  578|    647|        {
  579|    647|          auto num_value = StringToDouble(value, env);
  580|    647|          *dst_ptr = Any(num_value);
  581|    647|        }
  582|      0|        else
  583|      0|        {
  584|      0|          auto msg = StrCat(errorPrefix(),
  585|      0|                            "\nThe right operand is a string, "
  586|      0|                            "can't convert to ",
  587|      0|                            demangle(dst_ptr->type()));
  588|      0|          throw RuntimeError(msg);
  589|      0|        }
  590|    647|      }
  591|  1.74k|      else
  592|  1.74k|      {
  593|  1.74k|        try
  594|  1.74k|        {
  595|  1.74k|          value.copyInto(*dst_ptr);
  596|  1.74k|        }
  597|  1.74k|        catch(std::exception&)
  598|  1.74k|        {
  599|     53|          auto msg = StrCat(errorPrefix(), "\nThe right operand has type [",
  600|     53|                            BT::demangle(value.type()), "] and can't be converted to [",
  601|     53|                            BT::demangle(dst_ptr->type()), "]");
  602|     53|          throw RuntimeError(msg);
  603|     53|        }
  604|  1.74k|      }
  605|  10.2k|      entry->sequence_id++;
  606|  10.2k|      entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  607|  10.2k|      return *dst_ptr;
  608|  10.3k|    }
  609|       |
  610|  10.4k|    if(dst_ptr->empty())
  ------------------
  |  Branch (610:8): [True: 5, False: 10.4k]
  ------------------
  611|      5|    {
  612|      5|      throw RuntimeError(ErrorNotInit("left", opStr()));
  613|      5|    }
  614|       |
  615|       |    // temporary use
  616|  10.4k|    Any temp_variable = *dst_ptr;
  617|       |
  618|  10.4k|    if(value.isNumber())
  ------------------
  |  Branch (618:8): [True: 1.82k, False: 8.58k]
  ------------------
  619|  1.82k|    {
  620|  1.82k|      if(!temp_variable.isNumber())
  ------------------
  |  Branch (620:10): [True: 7, False: 1.81k]
  ------------------
  621|      7|      {
  622|      7|        throw RuntimeError("This Assignment operator can't be used "
  623|      7|                           "with a non-numeric type");
  624|      7|      }
  625|       |
  626|  1.81k|      auto lv = temp_variable.cast<double>();
  627|  1.81k|      auto rv = value.cast<double>();
  628|  1.81k|      switch(op)
  629|  1.81k|      {
  630|    514|        case assign_plus:
  ------------------
  |  Branch (630:9): [True: 514, False: 1.30k]
  ------------------
  631|    514|          temp_variable = Any(lv + rv);
  632|    514|          break;
  633|    456|        case assign_minus:
  ------------------
  |  Branch (633:9): [True: 456, False: 1.36k]
  ------------------
  634|    456|          temp_variable = Any(lv - rv);
  635|    456|          break;
  636|    452|        case assign_times:
  ------------------
  |  Branch (636:9): [True: 452, False: 1.36k]
  ------------------
  637|    452|          temp_variable = Any(lv * rv);
  638|    452|          break;
  639|    395|        case assign_div:
  ------------------
  |  Branch (639:9): [True: 395, False: 1.42k]
  ------------------
  640|    395|          temp_variable = Any(lv / rv);
  641|    395|          break;
  642|      0|        default: {
  ------------------
  |  Branch (642:9): [True: 0, False: 1.81k]
  ------------------
  643|      0|        }
  644|  1.81k|      }
  645|  1.81k|    }
  646|  8.58k|    else if(value.isString())
  ------------------
  |  Branch (646:13): [True: 5.70k, False: 2.87k]
  ------------------
  647|  5.70k|    {
  648|  5.70k|      if(op == assign_plus)
  ------------------
  |  Branch (648:10): [True: 5.69k, False: 5]
  ------------------
  649|  5.69k|      {
  650|  5.69k|        auto lv = temp_variable.cast<std::string>();
  651|  5.69k|        auto rv = value.cast<std::string>();
  652|  5.69k|        temp_variable = Any(lv + rv);
  653|  5.69k|      }
  654|      5|      else
  655|      5|      {
  656|      5|        throw RuntimeError("Operator not supported for strings");
  657|      5|      }
  658|  5.70k|    }
  659|       |
  660|  10.3k|    temp_variable.copyInto(*dst_ptr);
  661|  10.3k|    entry->sequence_id++;
  662|  10.3k|    entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
  663|  10.3k|    return *dst_ptr;
  664|  10.4k|  }
_ZN2BT3Ast12ErrorNotInitB5cxx11EPKcS2_:
   62|     78|{
   63|     78|  return StrCat("The ", side, " operand of the operator [", op_str,
   64|     78|                "] is not initialized");
   65|     78|}
_ZNK2BT3Ast14ExprAssignment5opStrEv:
  485|     50|  {
  486|     50|    switch(op)
  ------------------
  |  Branch (486:12): [True: 50, False: 0]
  ------------------
  487|     50|    {
  488|     29|      case assign_create:
  ------------------
  |  Branch (488:7): [True: 29, False: 21]
  ------------------
  489|     29|        return ":=";
  490|     16|      case assign_existing:
  ------------------
  |  Branch (490:7): [True: 16, False: 34]
  ------------------
  491|     16|        return "=";
  492|      1|      case assign_plus:
  ------------------
  |  Branch (492:7): [True: 1, False: 49]
  ------------------
  493|      1|        return "+=";
  494|      2|      case assign_minus:
  ------------------
  |  Branch (494:7): [True: 2, False: 48]
  ------------------
  495|      2|        return "-=";
  496|      1|      case assign_times:
  ------------------
  |  Branch (496:7): [True: 1, False: 49]
  ------------------
  497|      1|        return "*=";
  498|      1|      case assign_div:
  ------------------
  |  Branch (498:7): [True: 1, False: 49]
  ------------------
  499|      1|        return "/=";
  500|     50|    }
  501|      0|    return "";
  502|     50|  }
_ZN2BT3Ast14StringToDoubleERKNS_3AnyERKNS0_11EnvironmentE:
   32|   206k|{
   33|   206k|  const auto str = value.cast<std::string>();
   34|   206k|  if(str == "true")
  ------------------
  |  Branch (34:6): [True: 194, False: 205k]
  ------------------
   35|    194|  {
   36|    194|    return 1.0;
   37|    194|  }
   38|   205k|  if(str == "false")
  ------------------
  |  Branch (38:6): [True: 194, False: 205k]
  ------------------
   39|    194|  {
   40|    194|    return 0.0;
   41|    194|  }
   42|   205k|  if(env.enums)
  ------------------
  |  Branch (42:6): [True: 205k, False: 0]
  ------------------
   43|   205k|  {
   44|   205k|    auto it = env.enums->find(str);
   45|   205k|    if(it != env.enums->end())
  ------------------
  |  Branch (45:8): [True: 0, False: 205k]
  ------------------
   46|      0|    {
   47|      0|      return it->second;
   48|      0|    }
   49|   205k|  }
   50|   205k|  return value.cast<double>();
   51|   205k|}
_ZZNK2BT3Ast14ExprAssignment8evaluateERNS0_11EnvironmentEENKUlvE_clB5cxx11Ev:
  548|     53|    auto errorPrefix = [dst_ptr, &key]() {
  549|     53|      return StrCat("Error assigning a value to entry [", key, "] with type [",
  550|     53|                    BT::demangle(dst_ptr->type()), "]. ");
  551|     53|    };
_ZN2BT3Ast6ExprIfC2ESt10shared_ptrINS0_8ExprBaseEES4_S4_:
  453|  2.49k|    : condition(std::move(condition)), then(std::move(then)), else_(std::move(else_))
  454|  2.49k|  {}
_ZNK2BT3Ast6ExprIf8evaluateERNS0_11EnvironmentE:
  457|    614|  {
  458|    614|    const auto& v = condition->evaluate(env);
  459|    614|    bool valid = (v.isType<SimpleString>() && v.cast<SimpleString>().size() > 0) ||
  ------------------
  |  Branch (459:19): [True: 0, False: 614]
  |  Branch (459:47): [True: 0, False: 0]
  ------------------
  460|    604|                 (v.cast<double>() != 0.0);
  ------------------
  |  Branch (460:18): [True: 239, False: 365]
  ------------------
  461|    614|    if(valid)
  ------------------
  |  Branch (461:8): [True: 236, False: 378]
  ------------------
  462|    236|    {
  463|    236|      return then->evaluate(env);
  464|    236|    }
  465|    378|    else
  466|    378|    {
  467|    378|      return else_->evaluate(env);
  468|    378|    }
  469|    614|  }
_ZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentE:
  352|  12.8k|  {
  353|  12.8k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  354|  12.8k|      switch(op)
  355|  12.8k|      {
  356|  12.8k|        case equal:
  357|  12.8k|          if(!IsSame(lv, rv))
  358|  12.8k|            return false;
  359|  12.8k|          break;
  360|  12.8k|        case not_equal:
  361|  12.8k|          if(IsSame(lv, rv))
  362|  12.8k|            return false;
  363|  12.8k|          break;
  364|  12.8k|        case less:
  365|  12.8k|          if(lv >= rv)
  366|  12.8k|            return false;
  367|  12.8k|          break;
  368|  12.8k|        case greater:
  369|  12.8k|          if(lv <= rv)
  370|  12.8k|            return false;
  371|  12.8k|          break;
  372|  12.8k|        case less_equal:
  373|  12.8k|          if(lv > rv)
  374|  12.8k|            return false;
  375|  12.8k|          break;
  376|  12.8k|        case greater_equal:
  377|  12.8k|          if(lv < rv)
  378|  12.8k|            return false;
  379|  12.8k|          break;
  380|  12.8k|      }
  381|  12.8k|      return true;
  382|  12.8k|    };
  383|       |
  384|  12.8k|    auto lhs_v = operands[0]->evaluate(env);
  385|   245k|    for(auto i = 0u; i != ops.size(); ++i)
  ------------------
  |  Branch (385:22): [True: 241k, False: 4.59k]
  ------------------
  386|   241k|    {
  387|   241k|      auto rhs_v = operands[i + 1]->evaluate(env);
  388|       |
  389|   241k|      if(lhs_v.empty())
  ------------------
  |  Branch (389:10): [True: 10, False: 241k]
  ------------------
  390|     10|      {
  391|     10|        throw RuntimeError(ErrorNotInit("left", opStr(ops[i])));
  392|     10|      }
  393|   241k|      if(rhs_v.empty())
  ------------------
  |  Branch (393:10): [True: 4, False: 241k]
  ------------------
  394|      4|      {
  395|      4|        throw RuntimeError(ErrorNotInit("right", opStr(ops[i])));
  396|      4|      }
  397|   241k|      const Any False(0.0);
  398|       |
  399|   241k|      if(lhs_v.isNumber() && rhs_v.isNumber())
  ------------------
  |  Branch (399:10): [True: 129k, False: 111k]
  |  Branch (399:30): [True: 26.8k, False: 102k]
  ------------------
  400|  26.8k|      {
  401|  26.8k|        auto lv = lhs_v.cast<double>();
  402|  26.8k|        auto rv = rhs_v.cast<double>();
  403|  26.8k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (403:12): [True: 1.20k, False: 25.6k]
  ------------------
  404|  1.20k|        {
  405|  1.20k|          return False;
  406|  1.20k|        }
  407|  26.8k|      }
  408|   214k|      else if(lhs_v.isString() && rhs_v.isString())
  ------------------
  |  Branch (408:15): [True: 111k, False: 102k]
  |  Branch (408:35): [True: 8.66k, False: 102k]
  ------------------
  409|  8.66k|      {
  410|  8.66k|        auto lv = lhs_v.cast<SimpleString>();
  411|  8.66k|        auto rv = rhs_v.cast<SimpleString>();
  412|  8.66k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (412:12): [True: 4.18k, False: 4.47k]
  ------------------
  413|  4.18k|        {
  414|  4.18k|          return False;
  415|  4.18k|        }
  416|  8.66k|      }
  417|   205k|      else if(lhs_v.isString() && rhs_v.isNumber())
  ------------------
  |  Branch (417:15): [True: 102k, False: 102k]
  |  Branch (417:35): [True: 102k, False: 0]
  ------------------
  418|   102k|      {
  419|   102k|        auto lv = StringToDouble(lhs_v, env);
  420|   102k|        auto rv = rhs_v.cast<double>();
  421|   102k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (421:12): [True: 1.46k, False: 101k]
  ------------------
  422|  1.46k|        {
  423|  1.46k|          return False;
  424|  1.46k|        }
  425|   102k|      }
  426|   102k|      else if(lhs_v.isNumber() && rhs_v.isString())
  ------------------
  |  Branch (426:15): [True: 102k, False: 200]
  |  Branch (426:35): [True: 102k, False: 0]
  ------------------
  427|   102k|      {
  428|   102k|        auto lv = lhs_v.cast<double>();
  429|   102k|        auto rv = StringToDouble(rhs_v, env);
  430|   102k|        if(!SwitchImpl(lv, rv, ops[i]))
  ------------------
  |  Branch (430:12): [True: 1.23k, False: 101k]
  ------------------
  431|  1.23k|        {
  432|  1.23k|          return False;
  433|  1.23k|        }
  434|   102k|      }
  435|    200|      else
  436|    200|      {
  437|    200|        throw RuntimeError(StrCat("Can't mix different types in Comparison. "
  438|    200|                                  "Left operand [",
  439|    200|                                  BT::demangle(lhs_v.type()), "] right operand [",
  440|    200|                                  BT::demangle(rhs_v.type()), "]"));
  441|    200|      }
  442|   232k|      lhs_v = rhs_v;
  443|   232k|    }
  444|  4.59k|    return Any(1.0);
  445|  12.8k|  }
_ZNK2BT3Ast14ExprComparison5opStrENS1_4op_tE:
  329|     14|  {
  330|     14|    switch(op)
  ------------------
  |  Branch (330:12): [True: 14, False: 0]
  ------------------
  331|     14|    {
  332|      1|      case equal:
  ------------------
  |  Branch (332:7): [True: 1, False: 13]
  ------------------
  333|      1|        return "==";
  334|      2|      case not_equal:
  ------------------
  |  Branch (334:7): [True: 2, False: 12]
  ------------------
  335|      2|        return "!=";
  336|      3|      case less:
  ------------------
  |  Branch (336:7): [True: 3, False: 11]
  ------------------
  337|      3|        return "<";
  338|      7|      case greater:
  ------------------
  |  Branch (338:7): [True: 7, False: 7]
  ------------------
  339|      7|        return ">";
  340|      0|      case less_equal:
  ------------------
  |  Branch (340:7): [True: 0, False: 14]
  ------------------
  341|      0|        return "<=";
  342|      1|      case greater_equal:
  ------------------
  |  Branch (342:7): [True: 1, False: 13]
  ------------------
  343|      1|        return ">=";
  344|     14|    }
  345|      0|    return "";
  346|     14|  }
_ZZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentEENKUlRKT_RKT0_NS1_4op_tEE_clIddEEDaS6_S9_SA_:
  353|   232k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  354|   232k|      switch(op)
  ------------------
  |  Branch (354:14): [True: 232k, False: 0]
  ------------------
  355|   232k|      {
  356|  2.30k|        case equal:
  ------------------
  |  Branch (356:9): [True: 2.30k, False: 229k]
  ------------------
  357|  2.30k|          if(!IsSame(lv, rv))
  ------------------
  |  Branch (357:14): [True: 607, False: 1.69k]
  ------------------
  358|    607|            return false;
  359|  1.69k|          break;
  360|  16.5k|        case not_equal:
  ------------------
  |  Branch (360:9): [True: 16.5k, False: 215k]
  ------------------
  361|  16.5k|          if(IsSame(lv, rv))
  ------------------
  |  Branch (361:14): [True: 583, False: 15.9k]
  ------------------
  362|    583|            return false;
  363|  15.9k|          break;
  364|   105k|        case less:
  ------------------
  |  Branch (364:9): [True: 105k, False: 126k]
  ------------------
  365|   105k|          if(lv >= rv)
  ------------------
  |  Branch (365:14): [True: 723, False: 104k]
  ------------------
  366|    723|            return false;
  367|   104k|          break;
  368|   105k|        case greater:
  ------------------
  |  Branch (368:9): [True: 105k, False: 126k]
  ------------------
  369|   105k|          if(lv <= rv)
  ------------------
  |  Branch (369:14): [True: 811, False: 104k]
  ------------------
  370|    811|            return false;
  371|   104k|          break;
  372|   104k|        case less_equal:
  ------------------
  |  Branch (372:9): [True: 1.17k, False: 230k]
  ------------------
  373|  1.17k|          if(lv > rv)
  ------------------
  |  Branch (373:14): [True: 586, False: 592]
  ------------------
  374|    586|            return false;
  375|    592|          break;
  376|  1.33k|        case greater_equal:
  ------------------
  |  Branch (376:9): [True: 1.33k, False: 230k]
  ------------------
  377|  1.33k|          if(lv < rv)
  ------------------
  |  Branch (377:14): [True: 589, False: 742]
  ------------------
  378|    589|            return false;
  379|    742|          break;
  380|   232k|      }
  381|   228k|      return true;
  382|   232k|    };
_ZN2BT3Ast6IsSameIdEEbRKT_S4_:
  304|  18.8k|{
  305|       |  if constexpr(std::is_same_v<double, T>)
  306|  18.8k|  {
  307|  18.8k|    constexpr double EPS = static_cast<double>(std::numeric_limits<float>::epsilon());
  308|  18.8k|    return std::abs(lv - rv) <= EPS;
  309|       |  }
  310|       |  else
  311|       |  {
  312|       |    return (lv == rv);
  313|       |  }
  314|  18.8k|}
_ZZNK2BT3Ast14ExprComparison8evaluateERNS0_11EnvironmentEENKUlRKT_RKT0_NS1_4op_tEE_clIN7SafeAny12SimpleStringESE_EEDaS6_S9_SA_:
  353|  8.66k|    auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
  354|  8.66k|      switch(op)
  ------------------
  |  Branch (354:14): [True: 8.66k, False: 0]
  ------------------
  355|  8.66k|      {
  356|  1.04k|        case equal:
  ------------------
  |  Branch (356:9): [True: 1.04k, False: 7.62k]
  ------------------
  357|  1.04k|          if(!IsSame(lv, rv))
  ------------------
  |  Branch (357:14): [True: 648, False: 392]
  ------------------
  358|    648|            return false;
  359|    392|          break;
  360|  1.10k|        case not_equal:
  ------------------
  |  Branch (360:9): [True: 1.10k, False: 7.55k]
  ------------------
  361|  1.10k|          if(IsSame(lv, rv))
  ------------------
  |  Branch (361:14): [True: 509, False: 595]
  ------------------
  362|    509|            return false;
  363|    595|          break;
  364|  1.62k|        case less:
  ------------------
  |  Branch (364:9): [True: 1.62k, False: 7.03k]
  ------------------
  365|  1.62k|          if(lv >= rv)
  ------------------
  |  Branch (365:14): [True: 1.07k, False: 547]
  ------------------
  366|  1.07k|            return false;
  367|    547|          break;
  368|  1.59k|        case greater:
  ------------------
  |  Branch (368:9): [True: 1.59k, False: 7.06k]
  ------------------
  369|  1.59k|          if(lv <= rv)
  ------------------
  |  Branch (369:14): [True: 796, False: 795]
  ------------------
  370|    796|            return false;
  371|    795|          break;
  372|  1.46k|        case less_equal:
  ------------------
  |  Branch (372:9): [True: 1.46k, False: 7.19k]
  ------------------
  373|  1.46k|          if(lv > rv)
  ------------------
  |  Branch (373:14): [True: 523, False: 945]
  ------------------
  374|    523|            return false;
  375|    945|          break;
  376|  1.83k|        case greater_equal:
  ------------------
  |  Branch (376:9): [True: 1.83k, False: 6.82k]
  ------------------
  377|  1.83k|          if(lv < rv)
  ------------------
  |  Branch (377:14): [True: 636, False: 1.19k]
  ------------------
  378|    636|            return false;
  379|  1.19k|          break;
  380|  8.66k|      }
  381|  4.47k|      return true;
  382|  8.66k|    };
_ZN2BT3Ast6IsSameIN7SafeAny12SimpleStringEEEbRKT_S6_:
  304|  2.14k|{
  305|       |  if constexpr(std::is_same_v<double, T>)
  306|       |  {
  307|       |    constexpr double EPS = static_cast<double>(std::numeric_limits<float>::epsilon());
  308|       |    return std::abs(lv - rv) <= EPS;
  309|       |  }
  310|       |  else
  311|  2.14k|  {
  312|  2.14k|    return (lv == rv);
  313|  2.14k|  }
  314|  2.14k|}
_ZN2BT3Ast20ExprBinaryArithmeticC2ESt10shared_ptrINS0_8ExprBaseEENS1_4op_tES4_:
  199|  32.8k|    : op(op), lhs(std::move(lhs)), rhs(std::move(rhs))
  200|  32.8k|  {}
_ZNK2BT3Ast20ExprBinaryArithmetic8evaluateERNS0_11EnvironmentE:
  203|  12.6k|  {
  204|  12.6k|    auto lhs_v = lhs->evaluate(env);
  205|  12.6k|    auto rhs_v = rhs->evaluate(env);
  206|       |
  207|  12.6k|    if(lhs_v.empty())
  ------------------
  |  Branch (207:8): [True: 10, False: 12.5k]
  ------------------
  208|     10|    {
  209|     10|      throw RuntimeError(ErrorNotInit("left", opStr()));
  210|     10|    }
  211|  12.5k|    if(rhs_v.empty())
  ------------------
  |  Branch (211:8): [True: 4, False: 12.5k]
  ------------------
  212|      4|    {
  213|      4|      throw RuntimeError(ErrorNotInit("right", opStr()));
  214|      4|    }
  215|       |
  216|  12.5k|    if(rhs_v.isNumber() && lhs_v.isNumber())
  ------------------
  |  Branch (216:8): [True: 5.48k, False: 7.11k]
  |  Branch (216:28): [True: 3.98k, False: 1.49k]
  ------------------
  217|  3.98k|    {
  218|  3.98k|      auto lv = lhs_v.cast<double>();
  219|  3.98k|      auto rv = rhs_v.cast<double>();
  220|       |
  221|  3.98k|      switch(op)
  222|  3.98k|      {
  223|    406|        case plus:
  ------------------
  |  Branch (223:9): [True: 406, False: 3.58k]
  ------------------
  224|    406|          return Any(lv + rv);
  225|    425|        case minus:
  ------------------
  |  Branch (225:9): [True: 425, False: 3.56k]
  ------------------
  226|    425|          return Any(lv - rv);
  227|    276|        case times:
  ------------------
  |  Branch (227:9): [True: 276, False: 3.71k]
  ------------------
  228|    276|          return Any(lv * rv);
  229|    276|        case div:
  ------------------
  |  Branch (229:9): [True: 276, False: 3.71k]
  ------------------
  230|    276|          return Any(lv / rv);
  231|  2.60k|        default: {
  ------------------
  |  Branch (231:9): [True: 2.60k, False: 1.38k]
  ------------------
  232|  2.60k|        }
  233|  3.98k|      }
  234|       |
  235|  2.60k|      if(op == bit_and || op == bit_or || op == bit_xor)
  ------------------
  |  Branch (235:10): [True: 337, False: 2.26k]
  |  Branch (235:27): [True: 395, False: 1.86k]
  |  Branch (235:43): [True: 332, False: 1.53k]
  ------------------
  236|  1.06k|      {
  237|  1.06k|        try
  238|  1.06k|        {
  239|  1.06k|          int64_t li = lhs_v.cast<int64_t>();
  240|  1.06k|          int64_t ri = rhs_v.cast<int64_t>();
  241|  1.06k|          switch(op)
  242|  1.06k|          {
  243|    334|            case bit_and:
  ------------------
  |  Branch (243:13): [True: 334, False: 730]
  ------------------
  244|    334|              return Any(static_cast<double>(li & ri));
  245|    394|            case bit_or:
  ------------------
  |  Branch (245:13): [True: 394, False: 670]
  ------------------
  246|    394|              return Any(static_cast<double>(li | ri));
  247|    330|            case bit_xor:
  ------------------
  |  Branch (247:13): [True: 330, False: 734]
  ------------------
  248|    330|              return Any(static_cast<double>(li ^ ri));
  249|      0|            default: {
  ------------------
  |  Branch (249:13): [True: 0, False: 1.06k]
  ------------------
  250|      0|            }
  251|  1.06k|          }
  252|  1.06k|        }
  253|  1.06k|        catch(...)
  254|  1.06k|        {
  255|      6|          throw RuntimeError("Binary operators are not allowed if "
  256|      6|                             "one of the operands is not an integer");
  257|      6|        }
  258|  1.06k|      }
  259|       |
  260|  1.53k|      if(op == logic_or || op == logic_and)
  ------------------
  |  Branch (260:10): [True: 690, False: 846]
  |  Branch (260:28): [True: 609, False: 237]
  ------------------
  261|  1.29k|      {
  262|  1.29k|        try
  263|  1.29k|        {
  264|  1.29k|          auto lb = lhs_v.cast<bool>();
  265|  1.29k|          auto rb = rhs_v.cast<bool>();
  266|  1.29k|          switch(op)
  267|  1.29k|          {
  268|    631|            case logic_or:
  ------------------
  |  Branch (268:13): [True: 631, False: 668]
  ------------------
  269|    631|              return Any(static_cast<double>(lb || rb));
  ------------------
  |  Branch (269:46): [True: 229, False: 402]
  |  Branch (269:52): [True: 2, False: 400]
  ------------------
  270|    525|            case logic_and:
  ------------------
  |  Branch (270:13): [True: 525, False: 774]
  ------------------
  271|    525|              return Any(static_cast<double>(lb && rb));
  ------------------
  |  Branch (271:46): [True: 303, False: 222]
  |  Branch (271:52): [True: 294, False: 9]
  ------------------
  272|      0|            default: {
  ------------------
  |  Branch (272:13): [True: 0, False: 1.29k]
  ------------------
  273|      0|            }
  274|  1.29k|          }
  275|  1.29k|        }
  276|  1.29k|        catch(...)
  277|  1.29k|        {
  278|    143|          throw RuntimeError("Logic operators are not allowed if "
  279|    143|                             "one of the operands is not castable to bool");
  280|    143|        }
  281|  1.29k|      }
  282|  1.53k|    }
  283|  8.60k|    else if(rhs_v.isString() && lhs_v.isString() && op == plus)
  ------------------
  |  Branch (283:13): [True: 6.85k, False: 1.75k]
  |  Branch (283:33): [True: 5.02k, False: 1.82k]
  |  Branch (283:53): [True: 4.61k, False: 409]
  ------------------
  284|  4.61k|    {
  285|  4.61k|      return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
  286|  4.61k|    }
  287|  3.99k|    else if(op == concat && ((rhs_v.isString() && lhs_v.isString()) ||
  ------------------
  |  Branch (287:13): [True: 3.70k, False: 284]
  |  Branch (287:31): [True: 2.22k, False: 1.48k]
  |  Branch (287:51): [True: 401, False: 1.82k]
  ------------------
  288|  3.30k|                             (rhs_v.isString() && lhs_v.isNumber()) ||
  ------------------
  |  Branch (288:31): [True: 1.82k, False: 1.48k]
  |  Branch (288:51): [True: 1.82k, False: 0]
  ------------------
  289|  1.48k|                             (rhs_v.isNumber() && lhs_v.isString())))
  ------------------
  |  Branch (289:31): [True: 1.48k, False: 0]
  |  Branch (289:51): [True: 1.48k, False: 0]
  ------------------
  290|  3.70k|    {
  291|  3.70k|      return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
  292|  3.70k|    }
  293|    284|    else
  294|    284|    {
  295|    284|      throw RuntimeError("Operation not permitted");
  296|    284|    }
  297|       |
  298|    237|    return {};  // unreachable
  299|  12.5k|  }
_ZNK2BT3Ast20ExprBinaryArithmetic5opStrEv:
  169|     14|  {
  170|     14|    switch(op)
  ------------------
  |  Branch (170:12): [True: 14, False: 0]
  ------------------
  171|     14|    {
  172|      2|      case plus:
  ------------------
  |  Branch (172:7): [True: 2, False: 12]
  ------------------
  173|      2|        return "+";
  174|      0|      case minus:
  ------------------
  |  Branch (174:7): [True: 0, False: 14]
  ------------------
  175|      0|        return "-";
  176|      3|      case times:
  ------------------
  |  Branch (176:7): [True: 3, False: 11]
  ------------------
  177|      3|        return "*";
  178|      4|      case div:
  ------------------
  |  Branch (178:7): [True: 4, False: 10]
  ------------------
  179|      4|        return "/";
  180|      0|      case concat:
  ------------------
  |  Branch (180:7): [True: 0, False: 14]
  ------------------
  181|      0|        return "..";
  182|      2|      case bit_and:
  ------------------
  |  Branch (182:7): [True: 2, False: 12]
  ------------------
  183|      2|        return "&";
  184|      1|      case bit_or:
  ------------------
  |  Branch (184:7): [True: 1, False: 13]
  ------------------
  185|      1|        return "|";
  186|      1|      case bit_xor:
  ------------------
  |  Branch (186:7): [True: 1, False: 13]
  ------------------
  187|      1|        return "^";
  188|      0|      case logic_and:
  ------------------
  |  Branch (188:7): [True: 0, False: 14]
  ------------------
  189|      0|        return "&&";
  190|      1|      case logic_or:
  ------------------
  |  Branch (190:7): [True: 1, False: 13]
  ------------------
  191|      1|        return "||";
  192|     14|    }
  193|      0|    return "";
  194|     14|  }

_ZN7SafeAny7details13convertNumberIldEEvRKT_RT0_:
  152|   265k|{
  153|   265k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  154|   265k|                                                                          "convertible");
  155|       |
  156|   265k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (156:34): [True: 0, Folded]
  |  Branch (156:55): [Folded, False: 0]
  ------------------
  157|       |
  158|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  159|       |  {
  160|       |    if(source < 0)
  161|       |    {
  162|       |      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  163|       |    }
  164|       |  }
  165|       |  // these conversions are always safe (no check needed):
  166|       |  // - same type
  167|       |  // - float -> double
  168|       |  // - floating point to bool (C-style: any non-zero is true)
  169|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  170|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  171|       |  {
  172|       |    target = static_cast<DST>(source);
  173|       |  }
  174|       |  // integer to bool: only 0 and 1 are valid
  175|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  176|       |  {
  177|       |    checkLowerLimit<SRC, DST>(source);
  178|       |    target = static_cast<DST>(source);
  179|       |  }
  180|       |  else if constexpr(both_integers)
  181|       |  {
  182|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  183|       |    {
  184|       |      checkUpperLimit<SRC, DST>(source);
  185|       |    }
  186|       |    // casting to a smaller number need to be check
  187|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  188|       |    {
  189|       |      if constexpr(is_signed<SRC>())
  190|       |      {
  191|       |        checkLowerLimit<SRC, DST>(source);
  192|       |      }
  193|       |      checkUpperLimit<SRC, DST>(source);
  194|       |    }
  195|       |    target = static_cast<DST>(source);
  196|       |  }
  197|       |  // casting to/from floating points might cause truncation.
  198|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  199|       |                    std::is_floating_point<DST>::value)
  200|   265k|  {
  201|   265k|    bool both_float =
  202|   265k|        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  ------------------
  |  Branch (202:9): [Folded, False: 265k]
  |  Branch (202:47): [True: 0, Folded]
  ------------------
  203|       |    // to avoid being too pedantic, let's accept casting between double and float
  204|   265k|    if(!both_float)
  ------------------
  |  Branch (204:8): [True: 265k, False: 0]
  ------------------
  205|   265k|    {
  206|   265k|      checkTruncation<SRC, DST>(source);
  207|   265k|    }
  208|   265k|    target = static_cast<DST>(source);
  209|   265k|  }
  210|   265k|}
_ZN7SafeAny7details15checkTruncationIldEEvRKT_:
   92|   265k|{
   93|       |  // Handle integer to floating point
   94|       |  if constexpr(std::is_integral_v<From> && std::is_floating_point_v<To>)
   95|   265k|  {
   96|       |    // Check if value can be represented exactly in the target type
   97|   265k|    constexpr uint64_t max_exact = (1LL << std::numeric_limits<double>::digits) - 1;
   98|   265k|    bool doesnt_fit = false;
   99|       |    if constexpr(!std::is_signed_v<From>)
  100|       |    {
  101|       |      doesnt_fit = static_cast<uint64_t>(from) > max_exact;
  102|       |    }
  103|       |    else
  104|   265k|    {
  105|   265k|      doesnt_fit = std::abs(static_cast<int64_t>(from)) > static_cast<int64_t>(max_exact);
  106|   265k|    }
  107|   265k|    if(doesnt_fit)
  ------------------
  |  Branch (107:8): [True: 21, False: 265k]
  ------------------
  108|     21|    {
  109|     21|      throw std::runtime_error("Loss of precision when converting a large integer number "
  110|     21|                               "to floating point:" +
  111|     21|                               std::to_string(from));
  112|     21|    }
  113|       |  }
  114|       |  // Handle floating point to integer
  115|       |  else if constexpr(std::is_floating_point_v<From> && std::is_integral_v<To>)
  116|       |  {
  117|       |    // static_cast<From>(To::max) rounds up to an out-of-range value when To has
  118|       |    // more significant bits than From's mantissa (e.g. double -> int64_t). In
  119|       |    // that case a plain `>` lets the rounded boundary through and the cast to To
  120|       |    // below overflows, so use a half-open upper bound to reject it first.
  121|       |    constexpr bool max_rounds_up =
  122|       |        std::numeric_limits<To>::digits > std::numeric_limits<From>::digits;
  123|       |    const From max_limit = static_cast<From>(std::numeric_limits<To>::max());
  124|       |    const bool over = max_rounds_up ? (from >= max_limit) : (from > max_limit);
  125|       |    if(over || from < static_cast<From>(std::numeric_limits<To>::lowest()) ||
  126|       |       from != std::nearbyint(from))
  127|       |    {
  128|       |      throw std::runtime_error("Invalid floating point to integer conversion");
  129|       |    }
  130|       |  }
  131|       |  // Handle other conversions
  132|       |  else
  133|       |  {
  134|       |    if(from > static_cast<From>(std::numeric_limits<To>::max()) ||
  135|       |       from < static_cast<From>(std::numeric_limits<To>::lowest()))
  136|       |    {
  137|       |      throw std::runtime_error("Value outside numeric limits");
  138|       |    }
  139|       |    To as_target = static_cast<To>(from);
  140|       |    From back_to_source = static_cast<From>(as_target);
  141|       |    if(from != back_to_source)
  142|       |    {
  143|       |      throw std::runtime_error("Value truncated in conversion");
  144|       |    }
  145|       |  }
  146|   265k|}
_ZN7SafeAny7details13convertNumberIdlEEvRKT_RT0_:
  152|  2.03k|{
  153|  2.03k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  154|  2.03k|                                                                          "convertible");
  155|       |
  156|  2.03k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (156:34): [Folded, False: 2.03k]
  |  Branch (156:55): [True: 0, Folded]
  ------------------
  157|       |
  158|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  159|       |  {
  160|       |    if(source < 0)
  161|       |    {
  162|       |      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  163|       |    }
  164|       |  }
  165|       |  // these conversions are always safe (no check needed):
  166|       |  // - same type
  167|       |  // - float -> double
  168|       |  // - floating point to bool (C-style: any non-zero is true)
  169|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  170|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  171|       |  {
  172|       |    target = static_cast<DST>(source);
  173|       |  }
  174|       |  // integer to bool: only 0 and 1 are valid
  175|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  176|       |  {
  177|       |    checkLowerLimit<SRC, DST>(source);
  178|       |    target = static_cast<DST>(source);
  179|       |  }
  180|       |  else if constexpr(both_integers)
  181|       |  {
  182|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  183|       |    {
  184|       |      checkUpperLimit<SRC, DST>(source);
  185|       |    }
  186|       |    // casting to a smaller number need to be check
  187|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  188|       |    {
  189|       |      if constexpr(is_signed<SRC>())
  190|       |      {
  191|       |        checkLowerLimit<SRC, DST>(source);
  192|       |      }
  193|       |      checkUpperLimit<SRC, DST>(source);
  194|       |    }
  195|       |    target = static_cast<DST>(source);
  196|       |  }
  197|       |  // casting to/from floating points might cause truncation.
  198|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  199|       |                    std::is_floating_point<DST>::value)
  200|  2.03k|  {
  201|  2.03k|    bool both_float =
  202|  2.03k|        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  ------------------
  |  Branch (202:9): [True: 2.03k, Folded]
  |  Branch (202:47): [Folded, False: 2.03k]
  ------------------
  203|       |    // to avoid being too pedantic, let's accept casting between double and float
  204|  2.03k|    if(!both_float)
  ------------------
  |  Branch (204:8): [True: 2.03k, False: 0]
  ------------------
  205|  2.03k|    {
  206|  2.03k|      checkTruncation<SRC, DST>(source);
  207|  2.03k|    }
  208|  2.03k|    target = static_cast<DST>(source);
  209|  2.03k|  }
  210|  2.03k|}
_ZN7SafeAny7details15checkTruncationIdlEEvRKT_:
   92|  2.03k|{
   93|       |  // Handle integer to floating point
   94|       |  if constexpr(std::is_integral_v<From> && std::is_floating_point_v<To>)
   95|       |  {
   96|       |    // Check if value can be represented exactly in the target type
   97|       |    constexpr uint64_t max_exact = (1LL << std::numeric_limits<double>::digits) - 1;
   98|       |    bool doesnt_fit = false;
   99|       |    if constexpr(!std::is_signed_v<From>)
  100|       |    {
  101|       |      doesnt_fit = static_cast<uint64_t>(from) > max_exact;
  102|       |    }
  103|       |    else
  104|       |    {
  105|       |      doesnt_fit = std::abs(static_cast<int64_t>(from)) > static_cast<int64_t>(max_exact);
  106|       |    }
  107|       |    if(doesnt_fit)
  108|       |    {
  109|       |      throw std::runtime_error("Loss of precision when converting a large integer number "
  110|       |                               "to floating point:" +
  111|       |                               std::to_string(from));
  112|       |    }
  113|       |  }
  114|       |  // Handle floating point to integer
  115|       |  else if constexpr(std::is_floating_point_v<From> && std::is_integral_v<To>)
  116|  2.03k|  {
  117|       |    // static_cast<From>(To::max) rounds up to an out-of-range value when To has
  118|       |    // more significant bits than From's mantissa (e.g. double -> int64_t). In
  119|       |    // that case a plain `>` lets the rounded boundary through and the cast to To
  120|       |    // below overflows, so use a half-open upper bound to reject it first.
  121|  2.03k|    constexpr bool max_rounds_up =
  122|  2.03k|        std::numeric_limits<To>::digits > std::numeric_limits<From>::digits;
  123|  2.03k|    const From max_limit = static_cast<From>(std::numeric_limits<To>::max());
  124|  2.03k|    const bool over = max_rounds_up ? (from >= max_limit) : (from > max_limit);
  ------------------
  |  Branch (124:23): [True: 2.03k, Folded]
  ------------------
  125|  2.03k|    if(over || from < static_cast<From>(std::numeric_limits<To>::lowest()) ||
  ------------------
  |  Branch (125:8): [True: 3, False: 2.02k]
  |  Branch (125:16): [True: 1, False: 2.02k]
  ------------------
  126|  2.02k|       from != std::nearbyint(from))
  ------------------
  |  Branch (126:8): [True: 8, False: 2.01k]
  ------------------
  127|     12|    {
  128|     12|      throw std::runtime_error("Invalid floating point to integer conversion");
  129|     12|    }
  130|       |  }
  131|       |  // Handle other conversions
  132|       |  else
  133|       |  {
  134|       |    if(from > static_cast<From>(std::numeric_limits<To>::max()) ||
  135|       |       from < static_cast<From>(std::numeric_limits<To>::lowest()))
  136|       |    {
  137|       |      throw std::runtime_error("Value outside numeric limits");
  138|       |    }
  139|       |    To as_target = static_cast<To>(from);
  140|       |    From back_to_source = static_cast<From>(as_target);
  141|       |    if(from != back_to_source)
  142|       |    {
  143|       |      throw std::runtime_error("Value truncated in conversion");
  144|       |    }
  145|       |  }
  146|  2.03k|}
_ZN7SafeAny7details13convertNumberIlbEEvRKT_RT0_:
  152|  1.46k|{
  153|  1.46k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  154|  1.46k|                                                                          "convertible");
  155|       |
  156|  1.46k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (156:34): [True: 0, Folded]
  |  Branch (156:55): [True: 0, Folded]
  ------------------
  157|       |
  158|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  159|  1.46k|  {
  160|  1.46k|    if(source < 0)
  ------------------
  |  Branch (160:8): [True: 59, False: 1.40k]
  ------------------
  161|     59|    {
  162|     59|      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  163|     59|    }
  164|  1.46k|  }
  165|       |  // these conversions are always safe (no check needed):
  166|       |  // - same type
  167|       |  // - float -> double
  168|       |  // - floating point to bool (C-style: any non-zero is true)
  169|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  170|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  171|       |  {
  172|       |    target = static_cast<DST>(source);
  173|       |  }
  174|       |  // integer to bool: only 0 and 1 are valid
  175|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  176|  1.46k|  {
  177|  1.46k|    checkLowerLimit<SRC, DST>(source);
  178|  1.46k|    target = static_cast<DST>(source);
  179|       |  }
  180|       |  else if constexpr(both_integers)
  181|       |  {
  182|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  183|       |    {
  184|       |      checkUpperLimit<SRC, DST>(source);
  185|       |    }
  186|       |    // casting to a smaller number need to be check
  187|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  188|       |    {
  189|       |      if constexpr(is_signed<SRC>())
  190|       |      {
  191|       |        checkLowerLimit<SRC, DST>(source);
  192|       |      }
  193|       |      checkUpperLimit<SRC, DST>(source);
  194|       |    }
  195|       |    target = static_cast<DST>(source);
  196|       |  }
  197|       |  // casting to/from floating points might cause truncation.
  198|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  199|       |                    std::is_floating_point<DST>::value)
  200|       |  {
  201|       |    bool both_float =
  202|       |        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  203|       |    // to avoid being too pedantic, let's accept casting between double and float
  204|       |    if(!both_float)
  205|       |    {
  206|       |      checkTruncation<SRC, DST>(source);
  207|       |    }
  208|       |    target = static_cast<DST>(source);
  209|       |  }
  210|  1.46k|}
_ZN7SafeAny7details15checkLowerLimitIlbEEvRKT_:
   76|  1.40k|{
   77|       |  if constexpr(std::is_same<To, bool>::value)
   78|  1.40k|  {
   79|  1.40k|    if(from != 0 && from != 1)
  ------------------
  |  Branch (79:8): [True: 746, False: 657]
  |  Branch (79:21): [True: 83, False: 663]
  ------------------
   80|     83|    {
   81|     83|      throw std::runtime_error("Implicit casting to bool is not allowed");
   82|     83|    }
   83|       |  }
   84|       |  else if(from < std::numeric_limits<To>::min())
   85|       |  {
   86|       |    throw std::runtime_error("Value outside the lovest numerical limit.");
   87|       |  }
   88|  1.40k|}
_ZN7SafeAny7details13convertNumberIdbEEvRKT_RT0_:
  152|  1.03k|{
  153|  1.03k|  static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(), "Not "
  154|  1.03k|                                                                          "convertible");
  155|       |
  156|  1.03k|  constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
  ------------------
  |  Branch (156:34): [Folded, False: 1.03k]
  |  Branch (156:55): [True: 0, Folded]
  ------------------
  157|       |
  158|       |  if constexpr(is_signed<SRC>() && !is_signed<DST>())
  159|  1.03k|  {
  160|  1.03k|    if(source < 0)
  ------------------
  |  Branch (160:8): [True: 1, False: 1.03k]
  ------------------
  161|      1|    {
  162|      1|      throw std::runtime_error("Value is negative and can't be converted to unsigned");
  163|      1|    }
  164|  1.03k|  }
  165|       |  // these conversions are always safe (no check needed):
  166|       |  // - same type
  167|       |  // - float -> double
  168|       |  // - floating point to bool (C-style: any non-zero is true)
  169|       |  if constexpr(is_same<SRC, DST>() || (is_same<SRC, float>() && is_same<DST, double>()) ||
  170|       |               (std::is_floating_point<SRC>::value && is_same<DST, bool>()))
  171|  1.03k|  {
  172|  1.03k|    target = static_cast<DST>(source);
  173|       |  }
  174|       |  // integer to bool: only 0 and 1 are valid
  175|       |  else if constexpr(is_integer<SRC>() && is_same<DST, bool>())
  176|       |  {
  177|       |    checkLowerLimit<SRC, DST>(source);
  178|       |    target = static_cast<DST>(source);
  179|       |  }
  180|       |  else if constexpr(both_integers)
  181|       |  {
  182|       |    if constexpr(sizeof(SRC) == sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
  183|       |    {
  184|       |      checkUpperLimit<SRC, DST>(source);
  185|       |    }
  186|       |    // casting to a smaller number need to be check
  187|       |    else if constexpr(sizeof(SRC) > sizeof(DST))
  188|       |    {
  189|       |      if constexpr(is_signed<SRC>())
  190|       |      {
  191|       |        checkLowerLimit<SRC, DST>(source);
  192|       |      }
  193|       |      checkUpperLimit<SRC, DST>(source);
  194|       |    }
  195|       |    target = static_cast<DST>(source);
  196|       |  }
  197|       |  // casting to/from floating points might cause truncation.
  198|       |  else if constexpr(std::is_floating_point<SRC>::value ||
  199|       |                    std::is_floating_point<DST>::value)
  200|       |  {
  201|       |    bool both_float =
  202|       |        std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
  203|       |    // to avoid being too pedantic, let's accept casting between double and float
  204|       |    if(!both_float)
  205|       |    {
  206|       |      checkTruncation<SRC, DST>(source);
  207|       |    }
  208|       |    target = static_cast<DST>(source);
  209|       |  }
  210|  1.03k|}

_ZN2BT8demangleB5cxx11ERKSt10type_index:
   86|  16.8k|{
   87|  16.8k|  if(index == typeid(std::string))
  ------------------
  |  Branch (87:6): [True: 94, False: 16.7k]
  ------------------
   88|     94|  {
   89|     94|    return "std::string";
   90|     94|  }
   91|  16.7k|  if(index == typeid(std::string_view))
  ------------------
  |  Branch (91:6): [True: 0, False: 16.7k]
  ------------------
   92|      0|  {
   93|      0|    return "std::string_view";
   94|      0|  }
   95|  16.7k|  if(index == typeid(std::chrono::seconds))
  ------------------
  |  Branch (95:6): [True: 0, False: 16.7k]
  ------------------
   96|      0|  {
   97|      0|    return "std::chrono::seconds";
   98|      0|  }
   99|  16.7k|  if(index == typeid(std::chrono::milliseconds))
  ------------------
  |  Branch (99:6): [True: 0, False: 16.7k]
  ------------------
  100|      0|  {
  101|      0|    return "std::chrono::milliseconds";
  102|      0|  }
  103|  16.7k|  if(index == typeid(std::chrono::microseconds))
  ------------------
  |  Branch (103:6): [True: 0, False: 16.7k]
  ------------------
  104|      0|  {
  105|      0|    return "std::chrono::microseconds";
  106|      0|  }
  107|       |
  108|  16.7k|  scoped_demangled_name demangled_name(index.name());
  109|  16.7k|  char const* const p = demangled_name.get();
  110|  16.7k|  if(p != nullptr)
  ------------------
  |  Branch (110:6): [True: 16.7k, False: 0]
  ------------------
  111|  16.7k|  {
  112|  16.7k|    return p;
  113|  16.7k|  }
  114|      0|  return index.name();
  115|  16.7k|}
_ZN2BT21scoped_demangled_nameC2EPKc:
   34|  16.7k|  explicit scoped_demangled_name(char const* name) noexcept : m_p(demangle_alloc(name))
   35|  16.7k|  {}
_ZN2BT14demangle_allocEPKc:
   56|  16.7k|{
   57|  16.7k|  int status = 0;
   58|  16.7k|  std::size_t size = 0;
   59|       |  return abi::__cxa_demangle(name, NULL, &size, &status);
   60|  16.7k|}
_ZNK2BT21scoped_demangled_name3getEv:
   43|  16.7k|  {
   44|  16.7k|    return m_p;
   45|  16.7k|  }
_ZN2BT21scoped_demangled_nameD2Ev:
   38|  16.7k|  {
   39|  16.7k|    demangle_free(m_p);
   40|  16.7k|  }
_ZN2BT13demangle_freeEPKc:
   63|  16.7k|{
   64|       |  // NOLINTNEXTLINE(cppcoreguidelines-no-malloc,cppcoreguidelines-owning-memory)
   65|  16.7k|  std::free(const_cast<char*>(name));
   66|  16.7k|}

_ZNK2BT9LockedPtrINS_3AnyEEcvbEv:
   52|   108k|  {
   53|   108k|    return ref_ != nullptr;
   54|   108k|  }
_ZNK2BT9LockedPtrINS_3AnyEE3getEv:
   73|   107k|  {
   74|   107k|    return ref_;
   75|   107k|  }
_ZN2BT9LockedPtrINS_3AnyEED2Ev:
   28|   108k|  {
   29|   108k|    if(mutex_ != nullptr)
  ------------------
  |  Branch (29:8): [True: 107k, False: 564]
  ------------------
   30|   107k|    {
   31|   107k|      mutex_->unlock();
   32|   107k|    }
   33|   108k|  }
_ZN2BT9LockedPtrINS_3AnyEEC2Ev:
   20|    564|  LockedPtr() = default;
_ZN2BT9LockedPtrINS_3AnyEEC2EPS1_PSt5mutex:
   22|   107k|  LockedPtr(T* obj, std::mutex* obj_mutex) : ref_(obj), mutex_(obj_mutex)
   23|   107k|  {
   24|   107k|    mutex_->lock();
   25|   107k|  }

_ZNK2BT3Any8isNumberEv:
  354|   611k|{
  355|   611k|  return _any.type() == typeid(int64_t) || _any.type() == typeid(uint64_t) ||
  ------------------
  |  Branch (355:10): [True: 369k, False: 242k]
  |  Branch (355:44): [True: 0, False: 242k]
  ------------------
  356|   242k|         _any.type() == typeid(double);
  ------------------
  |  Branch (356:10): [True: 13.8k, False: 228k]
  ------------------
  357|   611k|}
_ZN2BT3AnyC2Ev:
   78|  63.4k|  Any() : _original_type(UndefinedAnyType)
   79|  63.4k|  {}
_ZN2BT3AnyD2Ev:
   81|  7.25M|  ~Any() = default;
_ZNK2BT3Any4castIdEET_v:
  169|   479k|  {
  170|   479k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 479k, False: 189]
  ------------------
  171|   479k|    {
  172|   479k|      return res.value();
  173|   479k|    }
  174|    189|    else
  175|    189|    {
  176|    189|      throw std::runtime_error(res.error());
  177|    189|    }
  178|   479k|  }
_ZNK2BT3Any7tryCastIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  522|   479k|{
  523|   479k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  524|   479k|                                              "can not cast to reference");
  525|       |
  526|   479k|  if(_any.empty())
  ------------------
  |  Branch (526:6): [True: 2, False: 479k]
  ------------------
  527|      2|  {
  528|      2|    throw std::runtime_error("Any::cast failed because it is empty");
  529|      2|  }
  530|       |
  531|   479k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (531:6): [True: 8.87k, False: 470k]
  ------------------
  532|  8.87k|  {
  533|  8.87k|    return linb::any_cast<T>(_any);
  534|  8.87k|  }
  535|       |
  536|       |  // special case when the output is an enum.
  537|       |  // We will try first a int conversion
  538|       |  if constexpr(std::is_enum_v<T>)
  539|       |  {
  540|       |    if(isNumber())
  541|       |    {
  542|       |      return static_cast<T>(convert<int>().value());
  543|       |    }
  544|       |    if(isString())
  545|       |    {
  546|       |      if(auto out = stringToNumber<int64_t>())
  547|       |      {
  548|       |        return static_cast<T>(out.value());
  549|       |      }
  550|       |    }
  551|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  552|       |  }
  553|       |
  554|   470k|  if(isString())
  ------------------
  |  Branch (554:6): [True: 205k, False: 265k]
  ------------------
  555|   205k|  {
  556|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  557|   205k|    {
  558|   205k|      if(auto out = stringToNumber<T>())
  ------------------
  |  Branch (558:15): [True: 205k, False: 166]
  ------------------
  559|   205k|      {
  560|   205k|        return out.value();
  561|   205k|      }
  562|    166|      else
  563|    166|      {
  564|    166|        return out;
  565|    166|      }
  566|   205k|    }
  567|   205k|  }
  568|       |
  569|   470k|  if(auto res = convert<T>())
  ------------------
  |  Branch (569:11): [True: 265k, False: 205k]
  ------------------
  570|   265k|  {
  571|   265k|    return std::move(res.value());
  572|   265k|  }
  573|   205k|  else
  574|   205k|  {
  575|   205k|    return res;
  576|   205k|  }
  577|   470k|}
_ZNK2BT3Any10castedTypeEv:
  200|   755k|  {
  201|   755k|    return _any.type();
  202|   755k|  }
_ZNK2BT3Any8isStringEv:
  141|  1.38M|  {
  142|  1.38M|    return _any.type() == typeid(SafeAny::SimpleString);
  143|  1.38M|  }
_ZNK2BT3Any14stringToNumberIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  430|   205k|{
  431|   205k|  static_assert(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>, "Expecting a "
  432|   205k|                                                                     "numeric type");
  433|       |
  434|   205k|  const auto str = linb::any_cast<SafeAny::SimpleString>(_any);
  435|       |#if __cpp_lib_to_chars >= 201611L
  436|       |  T out;
  437|       |  auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), out);
  438|       |  if(err == std::errc())
  439|       |  {
  440|       |    return out;
  441|       |  }
  442|       |  else
  443|       |  {
  444|       |    return nonstd::make_unexpected("Any failed string to number conversion");
  445|       |  }
  446|       |#else
  447|   205k|  try
  448|   205k|  {
  449|       |    if constexpr(std::is_same_v<T, uint16_t>)
  450|       |    {
  451|       |      return std::stoul(str.toStdString());
  452|       |    }
  453|       |    if constexpr(std::is_integral_v<T>)
  454|       |    {
  455|       |      const int64_t val = std::stol(str.toStdString());
  456|       |      Any temp_any(val);
  457|       |      return temp_any.convert<T>();
  458|       |    }
  459|       |    if constexpr(std::is_floating_point_v<T>)
  460|   205k|    {
  461|   205k|      return std::stod(str.toStdString());
  462|   205k|    }
  463|   205k|  }
  464|   205k|  catch(...)
  465|   205k|  {
  466|    166|    return nonstd::make_unexpected("Any failed string to number conversion");
  467|    166|  }
  468|      0|#endif
  469|      0|  return nonstd::make_unexpected("Any conversion from string failed");
  470|   205k|}
_ZNK2BT3Any7convertIdEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  495|   265k|{
  496|   265k|  using SafeAny::details::convertNumber;
  497|   265k|  DST out;
  498|       |
  499|   265k|  const auto& type = _any.type();
  500|       |
  501|   265k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (501:6): [True: 265k, False: 0]
  ------------------
  502|   265k|  {
  503|   265k|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  504|   265k|  }
  505|      0|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (505:11): [True: 0, False: 0]
  ------------------
  506|      0|  {
  507|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  508|      0|  }
  509|      0|  else if(type == typeid(double))
  ------------------
  |  Branch (509:11): [True: 0, False: 0]
  ------------------
  510|      0|  {
  511|      0|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  512|      0|  }
  513|      0|  else
  514|      0|  {
  515|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  516|      0|  }
  517|   265k|  return out;
  518|   265k|}
_ZNK2BT3Any4typeEv:
  194|  16.8k|  {
  195|  16.8k|    return _original_type;
  196|  16.8k|  }
_ZN2BT3AnyC2IiEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  118|  5.55k|    : _any(int64_t(value)), _original_type(typeid(T))
  119|  5.55k|  {}
_ZN2BT3AnyaSERKS0_:
  337|   262k|{
  338|   262k|  if(this != &other)
  ------------------
  |  Branch (338:6): [True: 262k, False: 0]
  ------------------
  339|   262k|  {
  340|   262k|    this->_any = other._any;
  341|   262k|    this->_original_type = other._original_type;
  342|   262k|  }
  343|   262k|  return *this;
  344|   262k|}
_ZN2BT3AnyaSEOS0_:
  347|  39.7k|{
  348|  39.7k|  this->_any = std::move(other._any);
  349|  39.7k|  this->_original_type = other._original_type;
  350|  39.7k|  return *this;
  351|  39.7k|}
_ZNK2BT3Any8copyIntoERS0_:
  365|  9.25k|{
  366|  9.25k|  if(dst.empty())
  ------------------
  |  Branch (366:6): [True: 0, False: 9.25k]
  ------------------
  367|      0|  {
  368|      0|    dst = *this;
  369|      0|    return;
  370|      0|  }
  371|       |
  372|  9.25k|  const auto& dst_type = dst.castedType();
  373|       |
  374|  9.25k|  if((castedType() == dst_type) || (isString() && dst.isString()))
  ------------------
  |  Branch (374:6): [True: 8.13k, False: 1.11k]
  |  Branch (374:37): [True: 5, False: 1.11k]
  |  Branch (374:51): [True: 0, False: 5]
  ------------------
  375|  8.13k|  {
  376|  8.13k|    dst._any = _any;
  377|  8.13k|  }
  378|  1.11k|  else if(isNumber() && dst.isNumber())
  ------------------
  |  Branch (378:11): [True: 1.11k, False: 5]
  |  Branch (378:25): [True: 1.06k, False: 47]
  ------------------
  379|  1.06k|  {
  380|  1.06k|    if(dst_type == typeid(int64_t))
  ------------------
  |  Branch (380:8): [True: 871, False: 195]
  ------------------
  381|    871|    {
  382|    871|      dst._any = cast<int64_t>();
  383|    871|    }
  384|    195|    else if(dst_type == typeid(uint64_t))
  ------------------
  |  Branch (384:13): [True: 0, False: 195]
  ------------------
  385|      0|    {
  386|      0|      dst._any = cast<uint64_t>();
  387|      0|    }
  388|    195|    else if(dst_type == typeid(double))
  ------------------
  |  Branch (388:13): [True: 195, False: 0]
  ------------------
  389|    195|    {
  390|    195|      dst._any = cast<double>();
  391|    195|    }
  392|      0|    else
  393|      0|    {
  394|      0|      throw std::runtime_error("Any::copyInto fails");
  395|      0|    }
  396|  1.06k|  }
  397|     52|  else
  398|     52|  {
  399|     52|    throw std::runtime_error("Any::copyInto fails");
  400|     52|  }
  401|  9.25k|}
_ZNK2BT3Any5emptyEv:
  205|   551k|  {
  206|   551k|    return _any.empty();
  207|   551k|  }
_ZNK2BT3Any4castIlEET_v:
  169|  2.99k|  {
  170|  2.99k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 2.98k, False: 12]
  ------------------
  171|  2.98k|    {
  172|  2.98k|      return res.value();
  173|  2.98k|    }
  174|     12|    else
  175|     12|    {
  176|     12|      throw std::runtime_error(res.error());
  177|     12|    }
  178|  2.99k|  }
_ZNK2BT3Any7tryCastIlEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  522|  2.99k|{
  523|  2.99k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  524|  2.99k|                                              "can not cast to reference");
  525|       |
  526|  2.99k|  if(_any.empty())
  ------------------
  |  Branch (526:6): [True: 0, False: 2.99k]
  ------------------
  527|      0|  {
  528|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  529|      0|  }
  530|       |
  531|  2.99k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (531:6): [True: 967, False: 2.03k]
  ------------------
  532|    967|  {
  533|    967|    return linb::any_cast<T>(_any);
  534|    967|  }
  535|       |
  536|       |  // special case when the output is an enum.
  537|       |  // We will try first a int conversion
  538|       |  if constexpr(std::is_enum_v<T>)
  539|       |  {
  540|       |    if(isNumber())
  541|       |    {
  542|       |      return static_cast<T>(convert<int>().value());
  543|       |    }
  544|       |    if(isString())
  545|       |    {
  546|       |      if(auto out = stringToNumber<int64_t>())
  547|       |      {
  548|       |        return static_cast<T>(out.value());
  549|       |      }
  550|       |    }
  551|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  552|       |  }
  553|       |
  554|  2.03k|  if(isString())
  ------------------
  |  Branch (554:6): [True: 0, False: 2.03k]
  ------------------
  555|      0|  {
  556|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  557|      0|    {
  558|      0|      if(auto out = stringToNumber<T>())
  ------------------
  |  Branch (558:15): [True: 0, False: 0]
  ------------------
  559|      0|      {
  560|      0|        return out.value();
  561|      0|      }
  562|      0|      else
  563|      0|      {
  564|      0|        return out;
  565|      0|      }
  566|      0|    }
  567|      0|  }
  568|       |
  569|  2.03k|  if(auto res = convert<T>())
  ------------------
  |  Branch (569:11): [True: 2.01k, False: 12]
  ------------------
  570|  2.01k|  {
  571|  2.01k|    return std::move(res.value());
  572|  2.01k|  }
  573|     12|  else
  574|     12|  {
  575|     12|    return res;
  576|     12|  }
  577|  2.03k|}
_ZN2BT3AnyC2IlEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  118|  1.78M|    : _any(int64_t(value)), _original_type(typeid(T))
  119|  1.78M|  {}
_ZNK2BT3Any7convertIlEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  495|  2.03k|{
  496|  2.03k|  using SafeAny::details::convertNumber;
  497|  2.03k|  DST out;
  498|       |
  499|  2.03k|  const auto& type = _any.type();
  500|       |
  501|  2.03k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (501:6): [True: 0, False: 2.03k]
  ------------------
  502|      0|  {
  503|      0|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  504|      0|  }
  505|  2.03k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (505:11): [True: 0, False: 2.03k]
  ------------------
  506|      0|  {
  507|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  508|      0|  }
  509|  2.03k|  else if(type == typeid(double))
  ------------------
  |  Branch (509:11): [True: 2.03k, False: 0]
  ------------------
  510|  2.03k|  {
  511|  2.03k|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  512|  2.03k|  }
  513|      0|  else
  514|      0|  {
  515|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  516|      0|  }
  517|  2.03k|  return out;
  518|  2.03k|}
_ZN2BT3AnyC2ERKd:
   90|   267k|  explicit Any(const double& value) : _any(value), _original_type(typeid(double))
   91|   267k|  {}
_ZN2BT3AnyC2IbEERKT_PNSt9enable_ifIXoosr3std11is_integralIS2_EE5valuesr3std7is_enumIS2_EE5valueEvE4typeE:
  118|  5.55k|    : _any(int64_t(value)), _original_type(typeid(T))
  119|  5.55k|  {}
_ZN2BT3AnyC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  100|   382k|    : _any(SafeAny::SimpleString(str)), _original_type(typeid(std::string))
  101|   382k|  {}
_ZN2BT3AnyC2ERKS0_:
   83|  2.55M|  Any(const Any& other) : _any(other._any), _original_type(other._original_type)
   84|  2.55M|  {}
_ZN2BT3AnyC2EOS0_:
   87|  2.16M|    : _any(std::move(other._any)), _original_type(other._original_type)
   88|  2.16M|  {}
_ZN2BT3AnyC2ERKSt10type_index:
  121|  31.5k|  Any(const std::type_index& type) : _original_type(type)
  122|  31.5k|  {}
_ZNK2BT3Any4castINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEET_v:
  169|   234k|  {
  170|   234k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 234k, False: 0]
  ------------------
  171|   234k|    {
  172|   234k|      return res.value();
  173|   234k|    }
  174|      0|    else
  175|      0|    {
  176|      0|      throw std::runtime_error(res.error());
  177|      0|    }
  178|   234k|  }
_ZNK2BT3Any7tryCastINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEN6nonstd13expected_lite8expectedIT_S7_EEv:
  522|   234k|{
  523|   234k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  524|   234k|                                              "can not cast to reference");
  525|       |
  526|   234k|  if(_any.empty())
  ------------------
  |  Branch (526:6): [True: 0, False: 234k]
  ------------------
  527|      0|  {
  528|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  529|      0|  }
  530|       |
  531|   234k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (531:6): [True: 0, False: 234k]
  ------------------
  532|      0|  {
  533|      0|    return linb::any_cast<T>(_any);
  534|      0|  }
  535|       |
  536|       |  // special case when the output is an enum.
  537|       |  // We will try first a int conversion
  538|       |  if constexpr(std::is_enum_v<T>)
  539|       |  {
  540|       |    if(isNumber())
  541|       |    {
  542|       |      return static_cast<T>(convert<int>().value());
  543|       |    }
  544|       |    if(isString())
  545|       |    {
  546|       |      if(auto out = stringToNumber<int64_t>())
  547|       |      {
  548|       |        return static_cast<T>(out.value());
  549|       |      }
  550|       |    }
  551|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  552|       |  }
  553|       |
  554|   234k|  if(isString())
  ------------------
  |  Branch (554:6): [True: 231k, False: 3.31k]
  ------------------
  555|   231k|  {
  556|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  557|       |    {
  558|       |      if(auto out = stringToNumber<T>())
  559|       |      {
  560|       |        return out.value();
  561|       |      }
  562|       |      else
  563|       |      {
  564|       |        return out;
  565|       |      }
  566|       |    }
  567|   231k|  }
  568|       |
  569|   234k|  if(auto res = convert<T>())
  ------------------
  |  Branch (569:11): [True: 234k, False: 0]
  ------------------
  570|   234k|  {
  571|   234k|    return std::move(res.value());
  572|   234k|  }
  573|      0|  else
  574|      0|  {
  575|      0|    return res;
  576|      0|  }
  577|   234k|}
_ZNK2BT3Any7convertINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEN6nonstd13expected_lite8expectedIT_S7_EEPNSt9enable_ifIXsr3std7is_sameISB_S7_EE5valueEvE4typeE:
  405|   234k|{
  406|   234k|  const auto& type = _any.type();
  407|       |
  408|   234k|  if(type == typeid(SafeAny::SimpleString))
  ------------------
  |  Branch (408:6): [True: 231k, False: 3.31k]
  ------------------
  409|   231k|  {
  410|   231k|    return linb::any_cast<SafeAny::SimpleString>(_any).toStdString();
  411|   231k|  }
  412|  3.31k|  else if(type == typeid(int64_t))
  ------------------
  |  Branch (412:11): [True: 948, False: 2.36k]
  ------------------
  413|    948|  {
  414|    948|    return std::to_string(linb::any_cast<int64_t>(_any));
  415|    948|  }
  416|  2.36k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (416:11): [True: 0, False: 2.36k]
  ------------------
  417|      0|  {
  418|      0|    return std::to_string(linb::any_cast<uint64_t>(_any));
  419|      0|  }
  420|  2.36k|  else if(type == typeid(double))
  ------------------
  |  Branch (420:11): [True: 2.36k, False: 0]
  ------------------
  421|  2.36k|  {
  422|  2.36k|    return std::to_string(linb::any_cast<double>(_any));
  423|  2.36k|  }
  424|       |
  425|      0|  return nonstd::make_unexpected(errorMsg<DST>());
  426|   234k|}
_ZNK2BT3Any6isTypeIN7SafeAny12SimpleStringEEEbv:
  148|    604|  {
  149|    604|    return _original_type == typeid(T);
  150|    604|  }
_ZNK2BT3Any4castIN7SafeAny12SimpleStringEEET_v:
  169|  17.3k|  {
  170|  17.3k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 17.3k, False: 0]
  ------------------
  171|  17.3k|    {
  172|  17.3k|      return res.value();
  173|  17.3k|    }
  174|      0|    else
  175|      0|    {
  176|      0|      throw std::runtime_error(res.error());
  177|      0|    }
  178|  17.3k|  }
_ZNK2BT3Any7tryCastIN7SafeAny12SimpleStringEEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  522|  17.3k|{
  523|  17.3k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  524|  17.3k|                                              "can not cast to reference");
  525|       |
  526|  17.3k|  if(_any.empty())
  ------------------
  |  Branch (526:6): [True: 0, False: 17.3k]
  ------------------
  527|      0|  {
  528|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  529|      0|  }
  530|       |
  531|  17.3k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (531:6): [True: 17.3k, False: 0]
  ------------------
  532|  17.3k|  {
  533|  17.3k|    return linb::any_cast<T>(_any);
  534|  17.3k|  }
  535|       |
  536|       |  // special case when the output is an enum.
  537|       |  // We will try first a int conversion
  538|       |  if constexpr(std::is_enum_v<T>)
  539|       |  {
  540|       |    if(isNumber())
  541|       |    {
  542|       |      return static_cast<T>(convert<int>().value());
  543|       |    }
  544|       |    if(isString())
  545|       |    {
  546|       |      if(auto out = stringToNumber<int64_t>())
  547|       |      {
  548|       |        return static_cast<T>(out.value());
  549|       |      }
  550|       |    }
  551|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  552|       |  }
  553|       |
  554|      0|  if(isString())
  ------------------
  |  Branch (554:6): [True: 0, False: 0]
  ------------------
  555|      0|  {
  556|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  557|       |    {
  558|       |      if(auto out = stringToNumber<T>())
  559|       |      {
  560|       |        return out.value();
  561|       |      }
  562|       |      else
  563|       |      {
  564|       |        return out;
  565|       |      }
  566|       |    }
  567|      0|  }
  568|       |
  569|      0|  if(auto res = convert<T>())
  ------------------
  |  Branch (569:11): [True: 0, False: 0]
  ------------------
  570|      0|  {
  571|      0|    return std::move(res.value());
  572|      0|  }
  573|      0|  else
  574|      0|  {
  575|      0|    return res;
  576|      0|  }
  577|      0|}
_ZNK2BT3Any4castIbEET_v:
  169|  2.49k|  {
  170|  2.49k|    if(auto res = tryCast<T>())
  ------------------
  |  Branch (170:13): [True: 2.35k, False: 143]
  ------------------
  171|  2.35k|    {
  172|  2.35k|      return res.value();
  173|  2.35k|    }
  174|    143|    else
  175|    143|    {
  176|    143|      throw std::runtime_error(res.error());
  177|    143|    }
  178|  2.49k|  }
_ZNK2BT3Any7tryCastIbEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEv:
  522|  2.49k|{
  523|  2.49k|  static_assert(!std::is_reference<T>::value, "Any::cast uses value semantic, "
  524|  2.49k|                                              "can not cast to reference");
  525|       |
  526|  2.49k|  if(_any.empty())
  ------------------
  |  Branch (526:6): [True: 0, False: 2.49k]
  ------------------
  527|      0|  {
  528|      0|    throw std::runtime_error("Any::cast failed because it is empty");
  529|      0|  }
  530|       |
  531|  2.49k|  if(castedType() == typeid(T))
  ------------------
  |  Branch (531:6): [True: 0, False: 2.49k]
  ------------------
  532|      0|  {
  533|      0|    return linb::any_cast<T>(_any);
  534|      0|  }
  535|       |
  536|       |  // special case when the output is an enum.
  537|       |  // We will try first a int conversion
  538|       |  if constexpr(std::is_enum_v<T>)
  539|       |  {
  540|       |    if(isNumber())
  541|       |    {
  542|       |      return static_cast<T>(convert<int>().value());
  543|       |    }
  544|       |    if(isString())
  545|       |    {
  546|       |      if(auto out = stringToNumber<int64_t>())
  547|       |      {
  548|       |        return static_cast<T>(out.value());
  549|       |      }
  550|       |    }
  551|       |    return nonstd::make_unexpected("Any::cast failed to cast to enum type");
  552|       |  }
  553|       |
  554|  2.49k|  if(isString())
  ------------------
  |  Branch (554:6): [True: 0, False: 2.49k]
  ------------------
  555|      0|  {
  556|       |    if constexpr(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
  557|       |    {
  558|       |      if(auto out = stringToNumber<T>())
  559|       |      {
  560|       |        return out.value();
  561|       |      }
  562|       |      else
  563|       |      {
  564|       |        return out;
  565|       |      }
  566|       |    }
  567|      0|  }
  568|       |
  569|  2.49k|  if(auto res = convert<T>())
  ------------------
  |  Branch (569:11): [True: 2.35k, False: 143]
  ------------------
  570|  2.35k|  {
  571|  2.35k|    return std::move(res.value());
  572|  2.35k|  }
  573|    143|  else
  574|    143|  {
  575|    143|    return res;
  576|    143|  }
  577|  2.49k|}
_ZNK2BT3Any7convertIbEEN6nonstd13expected_lite8expectedIT_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEEPNSt9enable_ifIXsr3std13is_arithmeticIS5_EE5valueEvE4typeE:
  495|  2.49k|{
  496|  2.49k|  using SafeAny::details::convertNumber;
  497|  2.49k|  DST out;
  498|       |
  499|  2.49k|  const auto& type = _any.type();
  500|       |
  501|  2.49k|  if(type == typeid(int64_t))
  ------------------
  |  Branch (501:6): [True: 1.46k, False: 1.03k]
  ------------------
  502|  1.46k|  {
  503|  1.46k|    convertNumber<int64_t, DST>(linb::any_cast<int64_t>(_any), out);
  504|  1.46k|  }
  505|  1.03k|  else if(type == typeid(uint64_t))
  ------------------
  |  Branch (505:11): [True: 0, False: 1.03k]
  ------------------
  506|      0|  {
  507|      0|    convertNumber<uint64_t, DST>(linb::any_cast<uint64_t>(_any), out);
  508|      0|  }
  509|  1.03k|  else if(type == typeid(double))
  ------------------
  |  Branch (509:11): [True: 1.03k, False: 0]
  ------------------
  510|  1.03k|  {
  511|  1.03k|    convertNumber<double, DST>(linb::any_cast<double>(_any), out);
  512|  1.03k|  }
  513|      0|  else
  514|      0|  {
  515|      0|    return nonstd::make_unexpected(errorMsg<DST>());
  516|      0|  }
  517|  2.49k|  return out;
  518|  2.49k|}

_ZN7SafeAny12SimpleStringC2ERKS0_:
   33|  1.20M|  SimpleString(const SimpleString& other) : SimpleString(other.data(), other.size())
   34|  1.20M|  {}
_ZNK7SafeAny12SimpleString4dataEv:
   87|  1.65M|  {
   88|  1.65M|    if(isSOO())
  ------------------
  |  Branch (88:8): [True: 1.55M, False: 95.6k]
  ------------------
   89|  1.55M|    {
   90|  1.55M|      return _storage.soo.data;
   91|  1.55M|    }
   92|  95.6k|    else
   93|  95.6k|    {
   94|  95.6k|      return _storage.str.data;
   95|  95.6k|    }
   96|  1.65M|  }
_ZNK7SafeAny12SimpleString5isSOOEv:
  155|  6.46M|  {
  156|  6.46M|    return (_storage.soo.capacity_left & IS_LONG_BIT) == 0;
  157|  6.46M|  }
_ZNK7SafeAny12SimpleString4sizeEv:
   99|  2.09M|  {
  100|  2.09M|    if(isSOO())
  ------------------
  |  Branch (100:8): [True: 1.98M, False: 117k]
  ------------------
  101|  1.98M|    {
  102|  1.98M|      return CAPACITY - _storage.soo.capacity_left;
  103|  1.98M|    }
  104|   117k|    else
  105|   117k|    {
  106|   117k|      return _storage.str.size & LONG_MASK;
  107|   117k|    }
  108|  2.09M|  }
_ZN7SafeAny12SimpleStringC2EPKcm:
   64|  1.58M|  {
   65|  1.58M|    createImpl(input_data, size);
   66|  1.58M|  }
_ZN7SafeAny12SimpleString10createImplEPKcm:
  184|  1.58M|  {
  185|  1.58M|    if(size > MAX_SIZE)
  ------------------
  |  Branch (185:8): [True: 17, False: 1.58M]
  ------------------
  186|     17|    {
  187|     17|      throw std::invalid_argument("size too large for a simple string");
  188|     17|    }
  189|       |
  190|  1.58M|    if(size > CAPACITY)
  ------------------
  |  Branch (190:8): [True: 96.1k, False: 1.48M]
  ------------------
  191|  96.1k|    {
  192|  96.1k|      _storage.str.size = size;
  193|  96.1k|      _storage.soo.capacity_left = IS_LONG_BIT;
  194|  96.1k|      _storage.str.data = new char[size + 1];  // NOLINT(cppcoreguidelines-owning-memory)
  195|  96.1k|      std::memcpy(_storage.str.data, input_data, size);
  196|  96.1k|      _storage.str.data[size] = '\0';
  197|  96.1k|    }
  198|  1.48M|    else
  199|  1.48M|    {
  200|  1.48M|      _storage.soo.capacity_left = uint8_t(CAPACITY - size);
  201|  1.48M|      if(size > 0)
  ------------------
  |  Branch (201:10): [True: 1.37M, False: 118k]
  ------------------
  202|  1.37M|      {
  203|  1.37M|        std::memcpy(_storage.soo.data, input_data, size);
  204|  1.37M|      }
  205|  1.48M|      if(size < CAPACITY)
  ------------------
  |  Branch (205:10): [True: 1.48M, False: 1.37k]
  ------------------
  206|  1.48M|      {
  207|  1.48M|        _storage.soo.data[size] = '\0';
  208|  1.48M|      }
  209|  1.48M|    }
  210|  1.58M|  }
_ZNK7SafeAny12SimpleString11toStdStringB5cxx11Ev:
   78|   437k|  {
   79|   437k|    return size() > 0 ? std::string(data(), size()) : std::string();
  ------------------
  |  Branch (79:12): [True: 433k, False: 3.58k]
  ------------------
   80|   437k|  }
_ZN7SafeAny12SimpleStringD2Ev:
   69|  2.71M|  {
   70|  2.71M|    if(!isSOO())
  ------------------
  |  Branch (70:8): [True: 96.1k, False: 2.62M]
  ------------------
   71|  96.1k|    {
   72|  96.1k|      delete[] _storage.str.data;
   73|  96.1k|    }
   74|  2.71M|    _storage.soo.capacity_left = CAPACITY;
   75|  2.71M|  }
_ZN7SafeAny12SimpleStringC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   27|   382k|  SimpleString(const std::string& str) : SimpleString(str.data(), str.size())
   28|   382k|  {}
_ZN7SafeAny12SimpleStringC2EOS0_:
   46|  1.13M|  SimpleString(SimpleString&& other) noexcept : SimpleString()
   47|  1.13M|  {
   48|  1.13M|    std::swap(_storage, other._storage);
   49|  1.13M|  }
_ZN7SafeAny12SimpleStringC2Ev:
   22|  1.13M|  {
   23|  1.13M|    _storage.soo.capacity_left = CAPACITY;
   24|  1.13M|    _storage.soo.data[0] = '\0';
   25|  1.13M|  }
_ZNK7SafeAny12SimpleStringeqERKS0_:
  111|  2.14k|  {
  112|  2.14k|    const size_t N = size();
  113|  2.14k|    return other.size() == N && std::strncmp(data(), other.data(), N) == 0;
  ------------------
  |  Branch (113:12): [True: 1.57k, False: 565]
  |  Branch (113:33): [True: 901, False: 678]
  ------------------
  114|  2.14k|  }
_ZNK7SafeAny12SimpleStringleERKS0_:
  123|  1.59k|  {
  124|  1.59k|    return !(*this > other);
  125|  1.59k|  }
_ZNK7SafeAny12SimpleStringgeERKS0_:
  128|  1.62k|  {
  129|  1.62k|    return !(*this < other);
  130|  1.62k|  }
_ZNK7SafeAny12SimpleStringltERKS0_:
  133|  3.45k|  {
  134|  3.45k|    const size_t min_size = std::min(size(), other.size());
  135|  3.45k|    int cmp = std::memcmp(data(), other.data(), min_size);
  136|  3.45k|    if(cmp != 0)
  ------------------
  |  Branch (136:8): [True: 1.38k, False: 2.07k]
  ------------------
  137|  1.38k|    {
  138|  1.38k|      return cmp < 0;
  139|  1.38k|    }
  140|  2.07k|    return size() < other.size();
  141|  3.45k|  }
_ZNK7SafeAny12SimpleStringgtERKS0_:
  144|  3.05k|  {
  145|  3.05k|    const size_t min_size = std::min(size(), other.size());
  146|  3.05k|    int cmp = std::memcmp(data(), other.data(), min_size);
  147|  3.05k|    if(cmp != 0)
  ------------------
  |  Branch (147:8): [True: 1.45k, False: 1.60k]
  ------------------
  148|  1.45k|    {
  149|  1.45k|      return cmp > 0;
  150|  1.45k|    }
  151|  1.60k|    return size() > other.size();
  152|  3.05k|  }

_ZN2BT6StrCatIJA2_cEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS5_ESB_SB_SB_DpRKT_:
   72|    192|{
   73|    192|  return strings_internal::CatPieces(
   74|    192|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|    192|}
_ZN2BT16strings_internal9CatPiecesB5cxx11ESt16initializer_listISt17basic_string_viewIcSt11char_traitsIcEEE:
   38|  6.35k|{
   39|  6.35k|  std::string out;
   40|  6.35k|  AppendPieces(&out, std::move(pieces));
   41|  6.35k|  return out;
   42|  6.35k|}
_ZN2BT16strings_internal12AppendPiecesEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt16initializer_listISt17basic_string_viewIcS4_EE:
   24|  6.35k|{
   25|  6.35k|  size_t size = 0;
   26|  6.35k|  for(const auto& piece : pieces)
  ------------------
  |  Branch (26:25): [True: 27.4k, False: 6.35k]
  ------------------
   27|  27.4k|  {
   28|  27.4k|    size += piece.size();
   29|  27.4k|  }
   30|  6.35k|  dest->reserve(dest->size() + size);
   31|  6.35k|  for(const auto& piece : pieces)
  ------------------
  |  Branch (31:25): [True: 27.4k, False: 6.35k]
  ------------------
   32|  27.4k|  {
   33|  27.4k|    dest->append(piece.data(), piece.size());
   34|  27.4k|  }
   35|  6.35k|}
_ZN2BT6StrCatB5cxx11ERKSt17basic_string_viewIcSt11char_traitsIcEE:
   52|  6.52k|{
   53|  6.52k|  return std::string(a.data(), a.size());
   54|  6.52k|}
_ZN2BT6StrCatB5cxx11ERKSt17basic_string_viewIcSt11char_traitsIcEES5_:
   57|    564|{
   58|    564|  return strings_internal::CatPieces({ a, b });
   59|    564|}
_ZN2BT6StrCatB5cxx11ERKSt17basic_string_viewIcSt11char_traitsIcEES5_S5_:
   63|    187|{
   64|    187|  return strings_internal::CatPieces({ a, b, c });
   65|    187|}
_ZN2BT6StrCatIJA8_cSt17basic_string_viewIcSt11char_traitsIcEEA3_cEEENSt7__cxx1112basic_stringIcS4_SaIcEEERKS5_SC_SC_SC_DpRKT_:
   72|    390|{
   73|    390|  return strings_internal::CatPieces(
   74|    390|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|    390|}
_ZN2BT6StrCatIJEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS4_ESA_SA_SA_DpRKT_:
   72|  3.04k|{
   73|  3.04k|  return strings_internal::CatPieces(
   74|  3.04k|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|  3.04k|}
_ZN2BT6StrCatIJA3_cEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS5_ESB_SB_SB_DpRKT_:
   72|  1.78k|{
   73|  1.78k|  return strings_internal::CatPieces(
   74|  1.78k|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|  1.78k|}
_ZN2BT6StrCatIJA21_cEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS5_ESB_SB_SB_DpRKT_:
   72|     78|{
   73|     78|  return strings_internal::CatPieces(
   74|     78|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|     78|}
_ZN2BT6StrCatIJA4_cEEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt17basic_string_viewIcS5_ESB_SB_SB_DpRKT_:
   72|     53|{
   73|     53|  return strings_internal::CatPieces(
   74|     53|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|     53|}
_ZN2BT6StrCatIJNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEA2_cEEES6_RKSt17basic_string_viewIcS4_ESB_SB_SB_DpRKT_:
   72|     53|{
   73|     53|  return strings_internal::CatPieces(
   74|     53|      { a, b, c, d, static_cast<const std::string_view&>(args)... });
   75|     53|}

_ZN2BT11parseDoubleESt17basic_string_viewIcSt11char_traitsIcEERdb:
  208|  6.01k|{
  209|       |#if defined(__cpp_lib_to_chars) && (__cpp_lib_to_chars >= 201611L)
  210|       |  // std::from_chars is locale-independent and thread-safe.
  211|       |  const char* begin = str.data();
  212|       |  const char* end = begin + str.size();
  213|       |  const auto [ptr, ec] = std::from_chars(begin, end, out);
  214|       |  if(ec != std::errc())
  215|       |  {
  216|       |    return false;
  217|       |  }
  218|       |  return !require_full_consumption || ptr == end;
  219|       |#else
  220|       |  // Apple's libc++ lacks the floating-point std::from_chars overload. Reproduce
  221|       |  // its std::chars_format::general semantics with strtod_l under a "C" locale
  222|       |  // created once (thread-safe, no global setlocale mutation), plus a guard that
  223|       |  // rejects the leading whitespace, leading '+', and hex floats that strtod
  224|       |  // would otherwise accept.
  225|  6.01k|  if(str.empty())
  ------------------
  |  Branch (225:6): [True: 0, False: 6.01k]
  ------------------
  226|      0|  {
  227|      0|    return false;
  228|      0|  }
  229|  6.01k|  const char first = str.front();
  230|  6.01k|  if(first == '+' || std::isspace(static_cast<unsigned char>(first)) != 0)
  ------------------
  |  Branch (230:6): [True: 0, False: 6.01k]
  |  Branch (230:22): [True: 0, False: 6.01k]
  ------------------
  231|      0|  {
  232|      0|    return false;
  233|      0|  }
  234|       |  // std::from_chars(general) does not recognise a "0x"/"0X" hex-float prefix; it
  235|       |  // parses only the leading "0" and stops at the 'x'. strtod would consume the
  236|       |  // whole hex float, so emulate from_chars here: the value is 0, and everything
  237|       |  // from the 'x' onward is unparsed (a failure only in the full-consumption case).
  238|  6.01k|  const std::size_t mantissa = (first == '-') ? 1u : 0u;
  ------------------
  |  Branch (238:32): [True: 0, False: 6.01k]
  ------------------
  239|  6.01k|  if(str.size() > mantissa + 1 && str[mantissa] == '0' &&
  ------------------
  |  Branch (239:6): [True: 6.01k, False: 0]
  |  Branch (239:35): [True: 1.79k, False: 4.21k]
  ------------------
  240|  1.79k|     (str[mantissa + 1] == 'x' || str[mantissa + 1] == 'X'))
  ------------------
  |  Branch (240:7): [True: 0, False: 1.79k]
  |  Branch (240:35): [True: 0, False: 1.79k]
  ------------------
  241|      0|  {
  242|      0|    if(require_full_consumption)
  ------------------
  |  Branch (242:8): [True: 0, False: 0]
  ------------------
  243|      0|    {
  244|      0|      return false;
  245|      0|    }
  246|      0|    out = (first == '-') ? -0.0 : 0.0;
  ------------------
  |  Branch (246:11): [True: 0, False: 0]
  ------------------
  247|      0|    return true;
  248|      0|  }
  249|  6.01k|  static ::locale_t c_locale =
  250|  6.01k|      ::newlocale(LC_NUMERIC_MASK, "C", static_cast<::locale_t>(0));
  251|  6.01k|  if(c_locale == static_cast<::locale_t>(0))
  ------------------
  |  Branch (251:6): [True: 0, False: 6.01k]
  ------------------
  252|      0|  {
  253|      0|    return false;
  254|      0|  }
  255|       |  // strtod_l needs a null-terminated buffer.
  256|  6.01k|  const std::string buffer(str.data(), str.size());
  257|  6.01k|  errno = 0;
  258|  6.01k|  char* parse_end = nullptr;
  259|  6.01k|  const double value = ::strtod_l(buffer.c_str(), &parse_end, c_locale);
  260|  6.01k|  if(parse_end == buffer.c_str() || errno == ERANGE)
  ------------------
  |  Branch (260:6): [True: 0, False: 6.01k]
  |  Branch (260:37): [True: 132, False: 5.87k]
  ------------------
  261|    132|  {
  262|    132|    return false;
  263|    132|  }
  264|  5.87k|  if(require_full_consumption && parse_end != buffer.c_str() + buffer.size())
  ------------------
  |  Branch (264:6): [True: 0, False: 5.87k]
  |  Branch (264:34): [True: 0, False: 0]
  ------------------
  265|      0|  {
  266|      0|    return false;
  267|      0|  }
  268|  5.87k|  out = value;
  269|  5.87k|  return true;
  270|  5.87k|#endif
  271|  5.87k|}
_ZN2BT17convertFromStringIdEET_St17basic_string_viewIcSt11char_traitsIcEE:
  275|  6.01k|{
  276|  6.01k|  double result = 0;
  277|  6.01k|  if(!parseDouble(str, result, /*require_full_consumption=*/false))
  ------------------
  |  Branch (277:6): [True: 132, False: 5.87k]
  ------------------
  278|    132|  {
  279|    132|    throw RuntimeError(StrCat("Can't convert string [", str, "] to double"));
  280|    132|  }
  281|  5.87k|  return result;
  282|  6.01k|}
_ZNK2BT8TypeInfo4typeEv:
  500|  39.5k|{
  501|  39.5k|  return type_info_;
  502|  39.5k|}
_ZN2BT9StartWithESt17basic_string_viewIcSt11char_traitsIcEEc:
  654|   311k|{
  655|   311k|  return str.size() >= 1 && str[0] == prefix;
  ------------------
  |  Branch (655:10): [True: 207k, False: 103k]
  |  Branch (655:29): [True: 111k, False: 95.6k]
  ------------------
  656|   311k|}

_ZN2BT10Blackboard12getAnyLockedERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   25|   108k|{
   26|   108k|  if(auto entry = getEntry(key))
  ------------------
  |  Branch (26:11): [True: 107k, False: 564]
  ------------------
   27|   107k|  {
   28|   107k|    return AnyPtrLocked(&entry->value, &entry->entry_mutex);
   29|   107k|  }
   30|    564|  return {};
   31|   108k|}
_ZNK2BT10Blackboard8getEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   55|   248k|{
   56|       |  // special syntax: "@" will always refer to the root BB
   57|   248k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (57:6): [True: 108k, False: 139k]
  ------------------
   58|   108k|  {
   59|   108k|    return rootBlackboard()->getEntry(key.substr(1, key.size() - 1));
   60|   108k|  }
   61|       |
   62|   139k|  {
   63|   139k|    const std::shared_lock<std::shared_mutex> storage_lock(storage_mutex_);
   64|   139k|    auto it = storage_.find(key);
   65|   139k|    if(it != storage_.end())
  ------------------
  |  Branch (65:8): [True: 129k, False: 10.0k]
  ------------------
   66|   129k|    {
   67|   129k|      return it->second;
   68|   129k|    }
   69|   139k|  }
   70|       |  // not found. Try autoremapping
   71|  10.0k|  if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (71:11): [True: 0, False: 10.0k]
  ------------------
   72|      0|  {
   73|      0|    auto remap_it = internal_to_external_.find(key);
   74|      0|    if(remap_it != internal_to_external_.cend())
  ------------------
  |  Branch (74:8): [True: 0, False: 0]
  ------------------
   75|      0|    {
   76|      0|      auto const& new_key = remap_it->second;
   77|      0|      return parent->getEntry(new_key);
   78|      0|    }
   79|      0|    if(autoremapping_ && !IsPrivateKey(key))
  ------------------
  |  Branch (79:8): [True: 0, False: 0]
  |  Branch (79:26): [True: 0, False: 0]
  ------------------
   80|      0|    {
   81|      0|      return parent->getEntry(key);
   82|      0|    }
   83|      0|  }
   84|  10.0k|  return {};
   85|  10.0k|}
_ZN2BT10Blackboard8getEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   88|   139k|{
   89|   139k|  return static_cast<const Blackboard&>(*this).getEntry(key);
   90|   139k|}
_ZN2BT10Blackboard9entryInfoERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
   93|    647|{
   94|    647|  auto entry = getEntry(key);
   95|    647|  return (!entry) ? nullptr : &(entry->info);
  ------------------
  |  Branch (95:10): [True: 0, False: 647]
  ------------------
   96|    647|}
_ZN2BT10Blackboard11createEntryERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_8TypeInfoE:
  165|  9.39k|{
  166|  9.39k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (166:6): [True: 3.06k, False: 6.33k]
  ------------------
  167|  3.06k|  {
  168|  3.06k|    if(key.find('@', 1) != std::string::npos)
  ------------------
  |  Branch (168:8): [True: 0, False: 3.06k]
  ------------------
  169|      0|    {
  170|      0|      throw LogicError("Character '@' used multiple times in the key");
  171|      0|    }
  172|  3.06k|    rootBlackboard()->createEntryImpl(key.substr(1, key.size() - 1), info);
  173|  3.06k|  }
  174|  6.33k|  else
  175|  6.33k|  {
  176|  6.33k|    createEntryImpl(key, info);
  177|  6.33k|  }
  178|  9.39k|}
_ZN2BT10Blackboard15createEntryImplERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_8TypeInfoE:
  284|  31.5k|{
  285|       |  // special syntax: "@" always refers to the root blackboard, the same
  286|       |  // redirection getEntry() applies. Without it, a key remapped to a root
  287|       |  // entry (port="{@foo}") is created here as a literal "@foo" entry that
  288|       |  // getEntry() then strips to "foo" and can never find again.
  289|  31.5k|  if(StartWith(key, '@'))
  ------------------
  |  Branch (289:6): [True: 0, False: 31.5k]
  ------------------
  290|      0|  {
  291|      0|    return rootBlackboard()->createEntryImpl(key.substr(1, key.size() - 1), info);
  292|      0|  }
  293|       |
  294|  31.5k|  const std::unique_lock storage_lock(storage_mutex_);
  295|       |  // This function might be called recursively, when we do remapping, because we move
  296|       |  // to the top scope to find already existing  entries
  297|       |
  298|       |  // search if exists already
  299|  31.5k|  auto storage_it = storage_.find(key);
  300|  31.5k|  if(storage_it != storage_.end())
  ------------------
  |  Branch (300:6): [True: 0, False: 31.5k]
  ------------------
  301|      0|  {
  302|      0|    const auto& prev_info = storage_it->second->info;
  303|      0|    if(prev_info.type() != info.type() && prev_info.isStronglyTyped() &&
  ------------------
  |  Branch (303:8): [True: 0, False: 0]
  |  Branch (303:43): [True: 0, False: 0]
  ------------------
  304|      0|       info.isStronglyTyped())
  ------------------
  |  Branch (304:8): [True: 0, False: 0]
  ------------------
  305|      0|    {
  306|      0|      auto msg = StrCat("Blackboard entry [", key,
  307|      0|                        "]: once declared, the type of a port"
  308|      0|                        " shall not change. Previously declared type [",
  309|      0|                        BT::demangle(prev_info.type()), "], current type [",
  310|      0|                        BT::demangle(info.type()), "]");
  311|       |
  312|      0|      throw LogicError(msg);
  313|      0|    }
  314|      0|    return storage_it->second;
  315|      0|  }
  316|       |
  317|       |  // manual remapping first
  318|  31.5k|  auto remapping_it = internal_to_external_.find(key);
  319|  31.5k|  if(remapping_it != internal_to_external_.end())
  ------------------
  |  Branch (319:6): [True: 0, False: 31.5k]
  ------------------
  320|      0|  {
  321|      0|    const auto& remapped_key = remapping_it->second;
  322|      0|    if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (322:13): [True: 0, False: 0]
  ------------------
  323|      0|    {
  324|      0|      return parent->createEntryImpl(remapped_key, info);
  325|      0|    }
  326|      0|    throw RuntimeError("Missing parent blackboard");
  327|      0|  }
  328|       |  // autoremapping second (excluding private keys)
  329|  31.5k|  if(autoremapping_ && !IsPrivateKey(key))
  ------------------
  |  Branch (329:6): [True: 0, False: 31.5k]
  |  Branch (329:24): [True: 0, False: 0]
  ------------------
  330|      0|  {
  331|      0|    if(auto parent = parent_bb_.lock())
  ------------------
  |  Branch (331:13): [True: 0, False: 0]
  ------------------
  332|      0|    {
  333|      0|      return parent->createEntryImpl(key, info);
  334|      0|    }
  335|      0|    throw RuntimeError("Missing parent blackboard");
  336|      0|  }
  337|       |  // not remapped, not found. Create locally.
  338|       |
  339|  31.5k|  auto entry = std::make_shared<Entry>(info);
  340|       |  // even if empty, let's assign to it a default type
  341|  31.5k|  entry->value = Any(info.type());
  342|  31.5k|  storage_.insert({ key, entry });
  343|  31.5k|  return entry;
  344|  31.5k|}
_ZN2BT10Blackboard14rootBlackboardEv:
  383|  3.06k|{
  384|  3.06k|  auto bb = static_cast<const Blackboard&>(*this).rootBlackboard();
  385|       |  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
  386|  3.06k|  return const_cast<Blackboard*>(bb);
  387|  3.06k|}
_ZNK2BT10Blackboard14rootBlackboardEv:
  390|   111k|{
  391|   111k|  const Blackboard* bb = this;
  392|   111k|  Blackboard::Ptr prev = parent_bb_.lock();
  393|   111k|  while(prev)
  ------------------
  |  Branch (393:9): [True: 0, False: 111k]
  ------------------
  394|      0|  {
  395|      0|    bb = prev.get();
  396|      0|    prev = bb->parent_bb_.lock();
  397|      0|  }
  398|   111k|  return bb;
  399|   111k|}

_ZN2BT9Scripting15parseStatementsERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  443|  12.6k|{
  444|  12.6k|  auto tokens = tokenize(script);
  445|  12.6k|  ScriptParser parser(std::move(tokens));
  446|  12.6k|  return parser.parseAll();
  447|  12.6k|}
_ZN2BT11ParseScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  454|  7.10k|{
  455|  7.10k|  try
  456|  7.10k|  {
  457|  7.10k|    auto exprs = Scripting::parseStatements(script);
  458|  7.10k|    if(exprs.empty())
  ------------------
  |  Branch (458:8): [True: 56, False: 7.04k]
  ------------------
  459|     56|    {
  460|     56|      return nonstd::make_unexpected("Empty Script");
  461|     56|    }
  462|  7.04k|    return [exprs = std::move(exprs), script](Ast::Environment& env) {
  463|  7.04k|      try
  464|  7.04k|      {
  465|  7.04k|        for(size_t i = 0; i < exprs.size() - 1; ++i)
  466|  7.04k|        {
  467|  7.04k|          exprs[i]->evaluate(env);
  468|  7.04k|        }
  469|  7.04k|        return exprs.back()->evaluate(env);
  470|  7.04k|      }
  471|  7.04k|      catch(RuntimeError& err)
  472|  7.04k|      {
  473|  7.04k|        throw RuntimeError(StrCat("Error in script [", script, "]\n", err.what()));
  474|  7.04k|      }
  475|  7.04k|    };
  476|  7.10k|  }
  477|  7.10k|  catch(RuntimeError& err)
  478|  7.10k|  {
  479|  3.04k|    return nonstd::make_unexpected(err.what());
  480|  3.04k|  }
  481|  7.10k|}
_ZN2BT21ParseScriptAndExecuteERNS_3Ast11EnvironmentERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  484|  5.55k|{
  485|  5.55k|  auto executor = ParseScript(script);
  486|  5.55k|  if(executor)
  ------------------
  |  Branch (486:6): [True: 3.99k, False: 1.55k]
  ------------------
  487|  3.99k|  {
  488|  3.99k|    try
  489|  3.99k|    {
  490|  3.99k|      return executor.value()(env);
  491|  3.99k|    }
  492|  3.99k|    catch(RuntimeError& err)
  493|  3.99k|    {
  494|    975|      return nonstd::make_unexpected(err.what());
  495|    975|    }
  496|  3.99k|  }
  497|  1.55k|  return nonstd::make_unexpected(executor.error());
  498|  5.55k|}
_ZN2BT14ValidateScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  501|  5.55k|{
  502|  5.55k|  try
  503|  5.55k|  {
  504|  5.55k|    auto exprs = Scripting::parseStatements(script);
  505|  5.55k|    if(exprs.empty())
  ------------------
  |  Branch (505:8): [True: 28, False: 5.52k]
  ------------------
  506|     28|    {
  507|     28|      return nonstd::make_unexpected("Empty Script");
  508|     28|    }
  509|  5.52k|    return {};
  510|  5.55k|  }
  511|  5.55k|  catch(RuntimeError& err)
  512|  5.55k|  {
  513|  1.52k|    return nonstd::make_unexpected(err.what());
  514|  1.52k|  }
  515|  5.55k|}
_ZN2BT9Scripting12ScriptParserC2ESt6vectorINS0_5TokenESaIS3_EE:
   28|  12.6k|  explicit ScriptParser(std::vector<Token> tokens) : tokens_(std::move(tokens))
   29|  12.6k|  {}
_ZN2BT9Scripting12ScriptParser8parseAllEv:
   32|  12.6k|  {
   33|  12.6k|    std::vector<Ast::expr_ptr> stmts;
   34|  7.87M|    while(!atEnd())
  ------------------
  |  Branch (34:11): [True: 7.86M, False: 12.6k]
  ------------------
   35|  7.86M|    {
   36|  7.86M|      stmts.push_back(parseExpr(0));
   37|       |      // consume optional semicolons between statements
   38|  7.87M|      while(check(TokenType::Semicolon))
  ------------------
  |  Branch (38:13): [True: 8.80k, False: 7.86M]
  ------------------
   39|  8.80k|      {
   40|  8.80k|        advance();
   41|  8.80k|      }
   42|  7.86M|    }
   43|  12.6k|    return stmts;
   44|  12.6k|  }
_ZNK2BT9Scripting12ScriptParser5atEndEv:
   81|  20.5M|  {
   82|  20.5M|    return peek().type == TokenType::EndOfInput;
   83|  20.5M|  }
_ZNK2BT9Scripting12ScriptParser4peekEv:
   68|  51.4M|  {
   69|  51.4M|    return tokens_[current_];
   70|  51.4M|  }
_ZN2BT9Scripting12ScriptParser9parseExprEi:
  264|  10.3M|  {
  265|       |    // Bound the recursion so a deeply nested expression can't overflow the
  266|       |    // stack. Every open paren / unary prefix / right-hand operand adds one
  267|       |    // parseExpr frame; depth_ is decremented before the normal return below so
  268|       |    // it tracks the current nesting rather than the total call count. A parse
  269|       |    // failure throws and discards the parser, so the error paths need no reset.
  270|  10.3M|    if(++depth_ > kMaxNestingDepth)
  ------------------
  |  Branch (270:8): [True: 192, False: 10.3M]
  ------------------
  271|    192|    {
  272|    192|      throw RuntimeError(StrCat("Parse error at position ", std::to_string(peek().pos),
  273|    192|                                ": expression nesting is too deep (limit ",
  274|    192|                                std::to_string(kMaxNestingDepth), ")"));
  275|    192|    }
  276|       |
  277|  10.3M|    auto left = parsePrefix();
  278|       |
  279|  10.4M|    while(true)
  ------------------
  |  Branch (279:11): [True: 10.3M, Folded]
  ------------------
  280|  10.3M|    {
  281|  10.3M|      auto tokType = peek().type;
  282|  10.3M|      int lbp = leftBP(tokType);
  283|  10.3M|      if(lbp < 0 || lbp < minBP)
  ------------------
  |  Branch (283:10): [True: 7.92M, False: 2.41M]
  |  Branch (283:21): [True: 2.26M, False: 152k]
  ------------------
  284|  10.1M|      {
  285|  10.1M|        break;
  286|  10.1M|      }
  287|       |
  288|       |      // Assignment (non-associative: parse once, then break)
  289|   152k|      if(isAssignment(tokType))
  ------------------
  |  Branch (289:10): [True: 63.5k, False: 88.6k]
  ------------------
  290|  63.5k|      {
  291|  63.5k|        left = parseAssignment(std::move(left));
  292|  63.5k|        break;
  293|  63.5k|      }
  294|       |
  295|       |      // Ternary (non-associative: parse once, then break)
  296|  88.6k|      if(tokType == TokenType::Question)
  ------------------
  |  Branch (296:10): [True: 7.11k, False: 81.5k]
  ------------------
  297|  7.11k|      {
  298|  7.11k|        left = parseTernary(std::move(left));
  299|  7.11k|        break;
  300|  7.11k|      }
  301|       |
  302|       |      // Chained comparison
  303|  81.5k|      if(isComparison(tokType))
  ------------------
  |  Branch (303:10): [True: 47.4k, False: 34.1k]
  ------------------
  304|  47.4k|      {
  305|  47.4k|        left = parseChainedComparison(std::move(left));
  306|  47.4k|        continue;
  307|  47.4k|      }
  308|       |
  309|       |      // Regular left-associative binary operator
  310|  34.1k|      const auto& opTok = advance();
  311|       |      // Right BP = LBP + 1 for left-associativity
  312|  34.1k|      auto right = parseExpr(lbp + 1);
  313|  34.1k|      left = makeBinary(std::move(left), opTok.type, std::move(right));
  314|  34.1k|    }
  315|       |
  316|  10.3M|    --depth_;
  317|  10.3M|    return left;
  318|  10.3M|  }
_ZN2BT9Scripting12ScriptParser11parsePrefixEv:
  172|  10.3M|  {
  173|  10.3M|    const auto& tok = peek();
  174|       |
  175|       |    // Unary minus
  176|  10.3M|    if(tok.type == TokenType::Minus)
  ------------------
  |  Branch (176:8): [True: 11.4k, False: 10.3M]
  ------------------
  177|  11.4k|    {
  178|  11.4k|      advance();
  179|  11.4k|      auto operand = parseExpr(kPrefixBP);
  180|  11.4k|      return std::make_shared<Ast::ExprUnaryArithmetic>(Ast::ExprUnaryArithmetic::negate,
  181|  11.4k|                                                        std::move(operand));
  182|  11.4k|    }
  183|       |    // Bitwise complement
  184|  10.3M|    if(tok.type == TokenType::Tilde)
  ------------------
  |  Branch (184:8): [True: 18.4k, False: 10.2M]
  ------------------
  185|  18.4k|    {
  186|  18.4k|      advance();
  187|  18.4k|      auto operand = parseExpr(kPrefixBP);
  188|  18.4k|      return std::make_shared<Ast::ExprUnaryArithmetic>(
  189|  18.4k|          Ast::ExprUnaryArithmetic::complement, std::move(operand));
  190|  18.4k|    }
  191|       |    // Logical NOT
  192|  10.2M|    if(tok.type == TokenType::Bang)
  ------------------
  |  Branch (192:8): [True: 7.16k, False: 10.2M]
  ------------------
  193|  7.16k|    {
  194|  7.16k|      advance();
  195|  7.16k|      auto operand = parseExpr(kPrefixBP);
  196|  7.16k|      return std::make_shared<Ast::ExprUnaryArithmetic>(
  197|  7.16k|          Ast::ExprUnaryArithmetic::logical_not, std::move(operand));
  198|  7.16k|    }
  199|       |    // Parenthesized expression
  200|  10.2M|    if(tok.type == TokenType::LeftParen)
  ------------------
  |  Branch (200:8): [True: 37.0k, False: 10.2M]
  ------------------
  201|  37.0k|    {
  202|  37.0k|      advance();
  203|  37.0k|      auto expr = parseExpr(0);
  204|  37.0k|      expect(TokenType::RightParen, "expected ')'");
  205|  37.0k|      return expr;
  206|  37.0k|    }
  207|       |    // Boolean literal
  208|  10.2M|    if(tok.type == TokenType::Boolean)
  ------------------
  |  Branch (208:8): [True: 1.61k, False: 10.2M]
  ------------------
  209|  1.61k|    {
  210|  1.61k|      advance();
  211|  1.61k|      double val = (tok.text == "true") ? 1.0 : 0.0;
  ------------------
  |  Branch (211:20): [True: 876, False: 736]
  ------------------
  212|  1.61k|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  213|  1.61k|    }
  214|       |    // Integer literal
  215|  10.2M|    if(tok.type == TokenType::Integer)
  ------------------
  |  Branch (215:8): [True: 1.78M, False: 8.46M]
  ------------------
  216|  1.78M|    {
  217|  1.78M|      advance();
  218|  1.78M|      int64_t val = 0;
  219|  1.78M|      const char* first = tok.text.data();
  220|  1.78M|      const char* last = first + tok.text.size();
  221|  1.78M|      if(tok.text.size() > 2 && tok.text[0] == '0' &&
  ------------------
  |  Branch (221:10): [True: 25.8k, False: 1.76M]
  |  Branch (221:33): [True: 3.99k, False: 21.8k]
  ------------------
  222|  3.99k|         (tok.text[1] == 'x' || tok.text[1] == 'X'))
  ------------------
  |  Branch (222:11): [True: 1.01k, False: 2.98k]
  |  Branch (222:33): [True: 2.10k, False: 877]
  ------------------
  223|  3.11k|      {
  224|  3.11k|        std::from_chars(first + 2, last, val, 16);
  225|  3.11k|      }
  226|  1.78M|      else
  227|  1.78M|      {
  228|  1.78M|        std::from_chars(first, last, val, 10);
  229|  1.78M|      }
  230|  1.78M|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  231|  1.78M|    }
  232|       |    // Real literal
  233|  8.46M|    if(tok.type == TokenType::Real)
  ------------------
  |  Branch (233:8): [True: 6.01k, False: 8.45M]
  ------------------
  234|  6.01k|    {
  235|  6.01k|      advance();
  236|  6.01k|      double val = convertFromString<double>(tok.text);
  237|  6.01k|      return std::make_shared<Ast::ExprLiteral>(Any(val));
  238|  6.01k|    }
  239|       |    // String literal
  240|  8.45M|    if(tok.type == TokenType::String)
  ------------------
  |  Branch (240:8): [True: 363k, False: 8.09M]
  ------------------
  241|   363k|    {
  242|   363k|      advance();
  243|   363k|      return std::make_shared<Ast::ExprLiteral>(Any(std::string(tok.text)));
  244|   363k|    }
  245|       |    // Identifier
  246|  8.09M|    if(tok.type == TokenType::Identifier)
  ------------------
  |  Branch (246:8): [True: 8.09M, False: 3.85k]
  ------------------
  247|  8.09M|    {
  248|  8.09M|      advance();
  249|  8.09M|      return std::make_shared<Ast::ExprName>(std::string(tok.text));
  250|  8.09M|    }
  251|       |    // Error token from tokenizer
  252|  3.85k|    if(tok.type == TokenType::Error)
  ------------------
  |  Branch (252:8): [True: 2.07k, False: 1.78k]
  ------------------
  253|  2.07k|    {
  254|  2.07k|      throw RuntimeError(
  255|  2.07k|          StrCat("Invalid token '", tok.text, "' at position ", std::to_string(tok.pos)));
  256|  2.07k|    }
  257|       |
  258|  1.78k|    throw RuntimeError(StrCat("Expected operand at position ", std::to_string(tok.pos),
  259|  1.78k|                              " (got '", tok.text, "')"));
  260|  3.85k|  }
_ZN2BT9Scripting12ScriptParser6expectENS0_9TokenTypeEPKc:
   91|  6.95k|  {
   92|  6.95k|    if(!check(type))
  ------------------
  |  Branch (92:8): [True: 390, False: 6.56k]
  ------------------
   93|    390|    {
   94|    390|      throw RuntimeError(StrCat("Parse error at position ", std::to_string(peek().pos),
   95|    390|                                ": ", msg, " (got '", peek().text, "')"));
   96|    390|    }
   97|  6.56k|    return advance();
   98|  6.95k|  }
_ZN2BT9Scripting12ScriptParser6leftBPENS0_9TokenTypeE:
  105|  10.3M|  {
  106|  10.3M|    switch(type)
  107|  10.3M|    {
  108|       |      // Assignment (level 1, non-associative)
  109|  29.5k|      case TokenType::ColonEqual:
  ------------------
  |  Branch (109:7): [True: 29.5k, False: 10.3M]
  ------------------
  110|  43.5k|      case TokenType::Equal:
  ------------------
  |  Branch (110:7): [True: 13.9k, False: 10.3M]
  ------------------
  111|  58.7k|      case TokenType::PlusEqual:
  ------------------
  |  Branch (111:7): [True: 15.2k, False: 10.3M]
  ------------------
  112|  60.4k|      case TokenType::MinusEqual:
  ------------------
  |  Branch (112:7): [True: 1.68k, False: 10.3M]
  ------------------
  113|  62.1k|      case TokenType::StarEqual:
  ------------------
  |  Branch (113:7): [True: 1.67k, False: 10.3M]
  ------------------
  114|  64.6k|      case TokenType::SlashEqual:
  ------------------
  |  Branch (114:7): [True: 2.51k, False: 10.3M]
  ------------------
  115|  64.6k|        return kAssignmentBP;
  116|       |      // Ternary (level 2, non-associative)
  117|  8.03k|      case TokenType::Question:
  ------------------
  |  Branch (117:7): [True: 8.03k, False: 10.3M]
  ------------------
  118|  8.03k|        return kTernaryBP;
  119|       |      // Logical OR (level 3)
  120|  2.75k|      case TokenType::PipePipe:
  ------------------
  |  Branch (120:7): [True: 2.75k, False: 10.3M]
  ------------------
  121|  2.75k|        return 6;
  122|       |      // Logical AND (level 4)
  123|  2.09k|      case TokenType::AmpAmp:
  ------------------
  |  Branch (123:7): [True: 2.09k, False: 10.3M]
  ------------------
  124|  2.09k|        return 8;
  125|       |      // Comparison (level 5, chainable)
  126|  8.83k|      case TokenType::EqualEqual:
  ------------------
  |  Branch (126:7): [True: 8.83k, False: 10.3M]
  ------------------
  127|  51.4k|      case TokenType::BangEqual:
  ------------------
  |  Branch (127:7): [True: 42.6k, False: 10.2M]
  ------------------
  128|   449k|      case TokenType::Less:
  ------------------
  |  Branch (128:7): [True: 397k, False: 9.94M]
  ------------------
  129|  2.26M|      case TokenType::Greater:
  ------------------
  |  Branch (129:7): [True: 1.81M, False: 8.52M]
  ------------------
  130|  2.27M|      case TokenType::LessEqual:
  ------------------
  |  Branch (130:7): [True: 7.28k, False: 10.3M]
  ------------------
  131|  2.28M|      case TokenType::GreaterEqual:
  ------------------
  |  Branch (131:7): [True: 13.8k, False: 10.3M]
  ------------------
  132|  2.28M|        return kComparisonBP;
  133|       |      // Bitwise OR/XOR (level 6)
  134|  7.66k|      case TokenType::Pipe:
  ------------------
  |  Branch (134:7): [True: 7.66k, False: 10.3M]
  ------------------
  135|  9.12k|      case TokenType::Caret:
  ------------------
  |  Branch (135:7): [True: 1.46k, False: 10.3M]
  ------------------
  136|  9.12k|        return 12;
  137|       |      // Bitwise AND (level 7)
  138|  3.70k|      case TokenType::Ampersand:
  ------------------
  |  Branch (138:7): [True: 3.70k, False: 10.3M]
  ------------------
  139|  3.70k|        return 14;
  140|       |      // Add/Sub/Concat (level 8)
  141|  17.6k|      case TokenType::Plus:
  ------------------
  |  Branch (141:7): [True: 17.6k, False: 10.3M]
  ------------------
  142|  21.8k|      case TokenType::Minus:
  ------------------
  |  Branch (142:7): [True: 4.22k, False: 10.3M]
  ------------------
  143|  35.5k|      case TokenType::DotDot:
  ------------------
  |  Branch (143:7): [True: 13.6k, False: 10.3M]
  ------------------
  144|  35.5k|        return 16;
  145|       |      // Mul/Div (level 9)
  146|  1.44k|      case TokenType::Star:
  ------------------
  |  Branch (146:7): [True: 1.44k, False: 10.3M]
  ------------------
  147|  3.11k|      case TokenType::Slash:
  ------------------
  |  Branch (147:7): [True: 1.66k, False: 10.3M]
  ------------------
  148|  3.11k|        return kMulDivBP;
  149|  7.92M|      default:
  ------------------
  |  Branch (149:7): [True: 7.92M, False: 2.41M]
  ------------------
  150|  7.92M|        return -1;
  151|  10.3M|    }
  152|  10.3M|  }
_ZN2BT9Scripting12ScriptParser12isAssignmentENS0_9TokenTypeE:
  162|   152k|  {
  163|   152k|    return type == TokenType::ColonEqual || type == TokenType::Equal ||
  ------------------
  |  Branch (163:12): [True: 29.5k, False: 122k]
  |  Branch (163:45): [True: 12.9k, False: 109k]
  ------------------
  164|   109k|           type == TokenType::PlusEqual || type == TokenType::MinusEqual ||
  ------------------
  |  Branch (164:12): [True: 15.2k, False: 94.5k]
  |  Branch (164:44): [True: 1.68k, False: 92.8k]
  ------------------
  165|  92.8k|           type == TokenType::StarEqual || type == TokenType::SlashEqual;
  ------------------
  |  Branch (165:12): [True: 1.66k, False: 91.1k]
  |  Branch (165:44): [True: 2.51k, False: 88.6k]
  ------------------
  166|   152k|  }
_ZN2BT9Scripting12ScriptParser15parseAssignmentESt10shared_ptrINS_3Ast8ExprBaseEE:
  321|  63.5k|  {
  322|  63.5k|    const auto& opTok = advance();
  323|  63.5k|    Ast::ExprAssignment::op_t op{};
  324|  63.5k|    switch(opTok.type)
  325|  63.5k|    {
  326|  29.5k|      case TokenType::ColonEqual:
  ------------------
  |  Branch (326:7): [True: 29.5k, False: 34.0k]
  ------------------
  327|  29.5k|        op = Ast::ExprAssignment::assign_create;
  328|  29.5k|        break;
  329|  12.9k|      case TokenType::Equal:
  ------------------
  |  Branch (329:7): [True: 12.9k, False: 50.6k]
  ------------------
  330|  12.9k|        op = Ast::ExprAssignment::assign_existing;
  331|  12.9k|        break;
  332|  15.2k|      case TokenType::PlusEqual:
  ------------------
  |  Branch (332:7): [True: 15.2k, False: 48.3k]
  ------------------
  333|  15.2k|        op = Ast::ExprAssignment::assign_plus;
  334|  15.2k|        break;
  335|  1.68k|      case TokenType::MinusEqual:
  ------------------
  |  Branch (335:7): [True: 1.68k, False: 61.8k]
  ------------------
  336|  1.68k|        op = Ast::ExprAssignment::assign_minus;
  337|  1.68k|        break;
  338|  1.66k|      case TokenType::StarEqual:
  ------------------
  |  Branch (338:7): [True: 1.66k, False: 61.9k]
  ------------------
  339|  1.66k|        op = Ast::ExprAssignment::assign_times;
  340|  1.66k|        break;
  341|  2.51k|      case TokenType::SlashEqual:
  ------------------
  |  Branch (341:7): [True: 2.51k, False: 61.0k]
  ------------------
  342|  2.51k|        op = Ast::ExprAssignment::assign_div;
  343|  2.51k|        break;
  344|      0|      default:
  ------------------
  |  Branch (344:7): [True: 0, False: 63.5k]
  ------------------
  345|      0|        throw RuntimeError("Internal error: unexpected assignment op");
  346|  63.5k|    }
  347|       |    // Parse RHS -- use minBP=0 to allow full expression
  348|  63.5k|    auto right = parseExpr(0);
  349|  63.5k|    return std::make_shared<Ast::ExprAssignment>(std::move(left), op, std::move(right));
  350|  63.5k|  }
_ZN2BT9Scripting12ScriptParser12parseTernaryESt10shared_ptrINS_3Ast8ExprBaseEE:
  353|  7.11k|  {
  354|  7.11k|    advance();                     // consume '?'
  355|  7.11k|    auto thenExpr = parseExpr(0);  // full expression inside
  356|  7.11k|    expect(TokenType::Colon, "expected ':' in ternary expression");
  357|  7.11k|    auto elseExpr = parseExpr(kTernaryBP);
  358|  7.11k|    return std::make_shared<Ast::ExprIf>(std::move(condition), std::move(thenExpr),
  359|  7.11k|                                         std::move(elseExpr));
  360|  7.11k|  }
_ZN2BT9Scripting12ScriptParser12isComparisonENS0_9TokenTypeE:
  155|  2.40M|  {
  156|  2.40M|    return type == TokenType::EqualEqual || type == TokenType::BangEqual ||
  ------------------
  |  Branch (156:12): [True: 12.8k, False: 2.39M]
  |  Branch (156:45): [True: 46.6k, False: 2.34M]
  ------------------
  157|  2.34M|           type == TokenType::Less || type == TokenType::Greater ||
  ------------------
  |  Branch (157:12): [True: 407k, False: 1.94M]
  |  Branch (157:39): [True: 1.82M, False: 112k]
  ------------------
  158|   112k|           type == TokenType::LessEqual || type == TokenType::GreaterEqual;
  ------------------
  |  Branch (158:12): [True: 11.7k, False: 100k]
  |  Branch (158:44): [True: 23.9k, False: 76.7k]
  ------------------
  159|  2.40M|  }
_ZN2BT9Scripting12ScriptParser22parseChainedComparisonESt10shared_ptrINS_3Ast8ExprBaseEE:
  363|  47.4k|  {
  364|  47.4k|    auto node = std::make_shared<Ast::ExprComparison>();
  365|  47.4k|    node->operands.push_back(std::move(first));
  366|       |
  367|  2.33M|    while(isComparison(peek().type))
  ------------------
  |  Branch (367:11): [True: 2.28M, False: 47.4k]
  ------------------
  368|  2.28M|    {
  369|  2.28M|      node->ops.push_back(mapComparisonOp(advance().type));
  370|       |      // Parse the next operand above comparison level
  371|       |      // so that arithmetic binds tighter
  372|  2.28M|      node->operands.push_back(parseExpr(kComparisonBP + 1));
  373|  2.28M|    }
  374|  47.4k|    return node;
  375|  47.4k|  }
_ZN2BT9Scripting12ScriptParser15mapComparisonOpENS0_9TokenTypeE:
  378|  2.28M|  {
  379|  2.28M|    switch(type)
  380|  2.28M|    {
  381|  8.66k|      case TokenType::EqualEqual:
  ------------------
  |  Branch (381:7): [True: 8.66k, False: 2.27M]
  ------------------
  382|  8.66k|        return Ast::ExprComparison::equal;
  383|  42.3k|      case TokenType::BangEqual:
  ------------------
  |  Branch (383:7): [True: 42.3k, False: 2.24M]
  ------------------
  384|  42.3k|        return Ast::ExprComparison::not_equal;
  385|   396k|      case TokenType::Less:
  ------------------
  |  Branch (385:7): [True: 396k, False: 1.88M]
  ------------------
  386|   396k|        return Ast::ExprComparison::less;
  387|  1.81M|      case TokenType::Greater:
  ------------------
  |  Branch (387:7): [True: 1.81M, False: 468k]
  ------------------
  388|  1.81M|        return Ast::ExprComparison::greater;
  389|  7.15k|      case TokenType::LessEqual:
  ------------------
  |  Branch (389:7): [True: 7.15k, False: 2.27M]
  ------------------
  390|  7.15k|        return Ast::ExprComparison::less_equal;
  391|  13.3k|      case TokenType::GreaterEqual:
  ------------------
  |  Branch (391:7): [True: 13.3k, False: 2.26M]
  ------------------
  392|  13.3k|        return Ast::ExprComparison::greater_equal;
  393|      0|      default:
  ------------------
  |  Branch (393:7): [True: 0, False: 2.28M]
  ------------------
  394|      0|        throw RuntimeError("Internal error: not a comparison op");
  395|  2.28M|    }
  396|  2.28M|  }
_ZN2BT9Scripting12ScriptParser10makeBinaryESt10shared_ptrINS_3Ast8ExprBaseEENS0_9TokenTypeES5_:
  400|  32.8k|  {
  401|  32.8k|    Ast::ExprBinaryArithmetic::op_t op{};
  402|  32.8k|    switch(opType)
  403|  32.8k|    {
  404|  10.9k|      case TokenType::Plus:
  ------------------
  |  Branch (404:7): [True: 10.9k, False: 21.9k]
  ------------------
  405|  10.9k|        op = Ast::ExprBinaryArithmetic::plus;
  406|  10.9k|        break;
  407|  2.22k|      case TokenType::Minus:
  ------------------
  |  Branch (407:7): [True: 2.22k, False: 30.6k]
  ------------------
  408|  2.22k|        op = Ast::ExprBinaryArithmetic::minus;
  409|  2.22k|        break;
  410|    755|      case TokenType::Star:
  ------------------
  |  Branch (410:7): [True: 755, False: 32.0k]
  ------------------
  411|    755|        op = Ast::ExprBinaryArithmetic::times;
  412|    755|        break;
  413|    853|      case TokenType::Slash:
  ------------------
  |  Branch (413:7): [True: 853, False: 31.9k]
  ------------------
  414|    853|        op = Ast::ExprBinaryArithmetic::div;
  415|    853|        break;
  416|  9.26k|      case TokenType::DotDot:
  ------------------
  |  Branch (416:7): [True: 9.26k, False: 23.5k]
  ------------------
  417|  9.26k|        op = Ast::ExprBinaryArithmetic::concat;
  418|  9.26k|        break;
  419|  1.55k|      case TokenType::Ampersand:
  ------------------
  |  Branch (419:7): [True: 1.55k, False: 31.2k]
  ------------------
  420|  1.55k|        op = Ast::ExprBinaryArithmetic::bit_and;
  421|  1.55k|        break;
  422|  3.87k|      case TokenType::Pipe:
  ------------------
  |  Branch (422:7): [True: 3.87k, False: 28.9k]
  ------------------
  423|  3.87k|        op = Ast::ExprBinaryArithmetic::bit_or;
  424|  3.87k|        break;
  425|    719|      case TokenType::Caret:
  ------------------
  |  Branch (425:7): [True: 719, False: 32.1k]
  ------------------
  426|    719|        op = Ast::ExprBinaryArithmetic::bit_xor;
  427|    719|        break;
  428|  1.23k|      case TokenType::AmpAmp:
  ------------------
  |  Branch (428:7): [True: 1.23k, False: 31.6k]
  ------------------
  429|  1.23k|        op = Ast::ExprBinaryArithmetic::logic_and;
  430|  1.23k|        break;
  431|  1.44k|      case TokenType::PipePipe:
  ------------------
  |  Branch (431:7): [True: 1.44k, False: 31.4k]
  ------------------
  432|  1.44k|        op = Ast::ExprBinaryArithmetic::logic_or;
  433|  1.44k|        break;
  434|      0|      default:
  ------------------
  |  Branch (434:7): [True: 0, False: 32.8k]
  ------------------
  435|      0|        throw RuntimeError("Internal error: unknown binary operator");
  436|  32.8k|    }
  437|  32.8k|    return std::make_shared<Ast::ExprBinaryArithmetic>(std::move(left), op,
  438|  32.8k|                                                       std::move(right));
  439|  32.8k|  }
_ZNK2BT9Scripting12ScriptParser5checkENS0_9TokenTypeE:
   86|  7.87M|  {
   87|  7.87M|    return peek().type == type;
   88|  7.87M|  }
_ZN2BT9Scripting12ScriptParser7advanceEv:
   73|  12.7M|  {
   74|  12.7M|    const Token& tok = tokens_[current_];
   75|  12.7M|    if(!atEnd())
  ------------------
  |  Branch (75:8): [True: 12.7M, False: 0]
  ------------------
   76|  12.7M|      current_++;
   77|  12.7M|    return tok;
   78|  12.7M|  }
script_parser.cpp:_ZZN2BT11ParseScriptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENK3$_0clERNS_3Ast11EnvironmentE:
  462|  3.99k|    return [exprs = std::move(exprs), script](Ast::Environment& env) {
  463|  3.99k|      try
  464|  3.99k|      {
  465|   115k|        for(size_t i = 0; i < exprs.size() - 1; ++i)
  ------------------
  |  Branch (465:27): [True: 111k, False: 3.99k]
  ------------------
  466|   111k|        {
  467|   111k|          exprs[i]->evaluate(env);
  468|   111k|        }
  469|  3.99k|        return exprs.back()->evaluate(env);
  470|  3.99k|      }
  471|  3.99k|      catch(RuntimeError& err)
  472|  3.99k|      {
  473|    975|        throw RuntimeError(StrCat("Error in script [", script, "]\n", err.what()));
  474|    975|      }
  475|  3.99k|    };

_ZN2BT9Scripting8tokenizeERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE:
  224|  12.6k|{
  225|  12.6k|  std::vector<Token> tokens;
  226|  12.6k|  const size_t len = source.size();
  227|  12.6k|  size_t i = 0;
  228|       |
  229|  46.4M|  while(i < len)
  ------------------
  |  Branch (229:9): [True: 46.4M, False: 12.6k]
  ------------------
  230|  46.4M|  {
  231|  46.4M|    const char c = source[i];
  232|       |
  233|       |    // Skip whitespace (space, tab, newline, carriage return)
  234|  46.4M|    if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
  ------------------
  |  Branch (234:8): [True: 13.9k, False: 46.4M]
  |  Branch (234:20): [True: 7.65k, False: 46.4M]
  |  Branch (234:33): [True: 276k, False: 46.1M]
  |  Branch (234:46): [True: 5.41k, False: 46.1M]
  ------------------
  235|   303k|    {
  236|   303k|      ++i;
  237|   303k|      continue;
  238|   303k|    }
  239|       |
  240|  46.1M|    const size_t start = i;
  241|       |
  242|       |    // Single-quoted string literal
  243|  46.1M|    if(c == '\'')
  ------------------
  |  Branch (243:8): [True: 642k, False: 45.4M]
  ------------------
  244|   642k|    {
  245|   642k|      ++i;
  246|  61.8M|      while(i < len && source[i] != '\'')
  ------------------
  |  Branch (246:13): [True: 61.8M, False: 414]
  |  Branch (246:24): [True: 61.1M, False: 642k]
  ------------------
  247|  61.1M|      {
  248|  61.1M|        ++i;
  249|  61.1M|      }
  250|   642k|      if(i < len)
  ------------------
  |  Branch (250:10): [True: 642k, False: 414]
  ------------------
  251|   642k|      {
  252|       |        // extract content without quotes
  253|   642k|        std::string_view text(&source[start + 1], i - start - 1);
  254|   642k|        tokens.push_back({ TokenType::String, text, start });
  255|   642k|        ++i;  // skip closing quote
  256|   642k|      }
  257|    414|      else
  258|    414|      {
  259|    414|        std::string_view text(&source[start], i - start);
  260|    414|        tokens.push_back({ TokenType::Error, text, start });
  261|    414|      }
  262|   642k|      continue;
  263|   642k|    }
  264|       |
  265|       |    // Number literal (integer or real)
  266|  45.4M|    if(isDigit(c))
  ------------------
  |  Branch (266:8): [True: 4.66M, False: 40.8M]
  ------------------
  267|  4.66M|    {
  268|  4.66M|      NumberResult nr;
  269|  4.66M|      const bool is_hex =
  270|  4.66M|          c == '0' && i + 1 < len && (source[i + 1] == 'x' || source[i + 1] == 'X');
  ------------------
  |  Branch (270:11): [True: 510k, False: 4.15M]
  |  Branch (270:23): [True: 509k, False: 727]
  |  Branch (270:39): [True: 37.7k, False: 471k]
  |  Branch (270:63): [True: 8.18k, False: 463k]
  ------------------
  271|  4.66M|      if(is_hex)
  ------------------
  |  Branch (271:10): [True: 45.9k, False: 4.62M]
  ------------------
  272|  45.9k|      {
  273|  45.9k|        nr = scanHexNumber(source, len, i);
  274|  45.9k|      }
  275|  4.62M|      else
  276|  4.62M|      {
  277|  4.62M|        nr = scanDecimalNumber(source, len, i);
  278|  4.62M|      }
  279|       |
  280|  4.66M|      std::string_view text(&source[start], i - start);
  281|  4.66M|      if(nr.has_error)
  ------------------
  |  Branch (281:10): [True: 370k, False: 4.29M]
  ------------------
  282|   370k|      {
  283|   370k|        tokens.push_back({ TokenType::Error, text, start });
  284|   370k|      }
  285|  4.29M|      else if(nr.is_real)
  ------------------
  |  Branch (285:15): [True: 29.7k, False: 4.26M]
  ------------------
  286|  29.7k|      {
  287|  29.7k|        tokens.push_back({ TokenType::Real, text, start });
  288|  29.7k|      }
  289|  4.26M|      else
  290|  4.26M|      {
  291|  4.26M|        tokens.push_back({ TokenType::Integer, text, start });
  292|  4.26M|      }
  293|  4.66M|      continue;
  294|  4.66M|    }
  295|       |
  296|       |    // Identifier or keyword (true/false)
  297|  40.8M|    if(isIdentStart(c))
  ------------------
  |  Branch (297:8): [True: 10.6M, False: 30.1M]
  ------------------
  298|  10.6M|    {
  299|  10.6M|      ++i;  // consume start character (may not be isIdentChar, e.g. '@')
  300|  59.7M|      while(i < len && isIdentChar(source[i]))
  ------------------
  |  Branch (300:13): [True: 59.7M, False: 3.00k]
  |  Branch (300:24): [True: 49.1M, False: 10.6M]
  ------------------
  301|  49.1M|      {
  302|  49.1M|        ++i;
  303|  49.1M|      }
  304|  10.6M|      if(std::string_view text(&source[start], i - start); text == "true" || text == "fal"
  ------------------
  |  Branch (304:60): [True: 4.58k, False: 10.6M]
  |  Branch (304:78): [True: 1.38k, False: 10.6M]
  ------------------
  305|  10.6M|                                                                                     "se")
  306|  5.97k|      {
  307|  5.97k|        tokens.push_back({ TokenType::Boolean, text, start });
  308|  5.97k|      }
  309|  10.6M|      else
  310|  10.6M|      {
  311|  10.6M|        tokens.push_back({ TokenType::Identifier, text, start });
  312|  10.6M|      }
  313|  10.6M|      continue;
  314|  10.6M|    }
  315|       |
  316|       |    // Two-character operators (check before single-char)
  317|  30.1M|    if(i + 1 < len)
  ------------------
  |  Branch (317:8): [True: 30.1M, False: 2.36k]
  ------------------
  318|  30.1M|    {
  319|  30.1M|      TokenType two_char_type = matchTwoCharOp(c, source[i + 1]);
  320|  30.1M|      if(two_char_type != TokenType::Error)
  ------------------
  |  Branch (320:10): [True: 259k, False: 29.8M]
  ------------------
  321|   259k|      {
  322|   259k|        std::string_view text(&source[start], 2);
  323|   259k|        tokens.push_back({ two_char_type, text, start });
  324|   259k|        i += 2;
  325|   259k|        continue;
  326|   259k|      }
  327|  30.1M|    }
  328|       |
  329|       |    // Single-character operators and delimiters
  330|  29.8M|    std::string_view text(&source[start], 1);
  331|  29.8M|    tokens.push_back({ matchSingleCharOp(c), text, start });
  332|  29.8M|    ++i;
  333|  29.8M|  }
  334|       |
  335|       |  // Sentinel
  336|  12.6k|  tokens.push_back({ TokenType::EndOfInput, {}, i });
  337|  12.6k|  return tokens;
  338|  12.6k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_17isDigitEc:
   34|   101M|{
   35|   101M|  return std::isdigit(static_cast<unsigned char>(c)) != 0;
   36|   101M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_113scanHexNumberERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   59|  45.9k|{
   60|  45.9k|  NumberResult result;
   61|  45.9k|  i += 2;  // skip "0x"/"0X"
   62|  45.9k|  if(i >= len || !isHexDigit(source[i]))
  ------------------
  |  Branch (62:6): [True: 42, False: 45.9k]
  |  Branch (62:18): [True: 32.1k, False: 13.7k]
  ------------------
   63|  32.2k|  {
   64|  32.2k|    result.has_error = true;
   65|  32.2k|  }
   66|  13.7k|  else
   67|  13.7k|  {
   68|  2.57M|    while(i < len && isHexDigit(source[i]))
  ------------------
  |  Branch (68:11): [True: 2.57M, False: 525]
  |  Branch (68:22): [True: 2.55M, False: 13.2k]
  ------------------
   69|  2.55M|    {
   70|  2.55M|      ++i;
   71|  2.55M|    }
   72|  13.7k|  }
   73|       |  // Hex numbers don't support dot or exponent
   74|  45.9k|  if(i < len && (source[i] == '.' || isIdentChar(source[i])))
  ------------------
  |  Branch (74:6): [True: 45.3k, False: 567]
  |  Branch (74:18): [True: 1.88k, False: 43.4k]
  |  Branch (74:38): [True: 27.6k, False: 15.8k]
  ------------------
   75|  29.5k|  {
   76|  29.5k|    result.has_error = true;
   77|  29.5k|    consumeTrailingGarbage(source, len, i);
   78|  29.5k|  }
   79|  45.9k|  return result;
   80|  45.9k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_110isHexDigitEc:
   39|  2.61M|{
   40|  2.61M|  return std::isxdigit(static_cast<unsigned char>(c)) != 0;
   41|  2.61M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_122consumeTrailingGarbageERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   45|  32.5k|{
   46|   282k|  while(i < len && (isIdentChar(source[i]) || source[i] == '.'))
  ------------------
  |  Branch (46:9): [True: 282k, False: 186]
  |  Branch (46:21): [True: 245k, False: 36.4k]
  |  Branch (46:47): [True: 4.04k, False: 32.3k]
  ------------------
   47|   249k|  {
   48|   249k|    ++i;
   49|   249k|  }
   50|  32.5k|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_117scanDecimalNumberERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEmRm:
   83|  4.62M|{
   84|  4.62M|  NumberResult result;
   85|       |
   86|       |  // Integer part
   87|  27.2M|  while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (87:9): [True: 27.2M, False: 2.32k]
  |  Branch (87:20): [True: 22.5M, False: 4.61M]
  ------------------
   88|  22.5M|  {
   89|  22.5M|    ++i;
   90|  22.5M|  }
   91|       |  // Fractional part
   92|  4.62M|  if(i < len && source[i] == '.')
  ------------------
  |  Branch (92:6): [True: 4.61M, False: 2.32k]
  |  Branch (92:17): [True: 22.1k, False: 4.59M]
  ------------------
   93|  22.1k|  {
   94|       |    // Distinguish from ".." (concat operator)
   95|  22.1k|    if(i + 1 < len && source[i + 1] == '.')
  ------------------
  |  Branch (95:8): [True: 22.1k, False: 18]
  |  Branch (95:23): [True: 10.0k, False: 12.0k]
  ------------------
   96|  10.0k|    {
   97|       |      // Stop here: "65.." is Integer("65") + DotDot
   98|  10.0k|    }
   99|  12.0k|    else if(i + 1 < len && isDigit(source[i + 1]))
  ------------------
  |  Branch (99:13): [True: 12.0k, False: 18]
  |  Branch (99:28): [True: 9.04k, False: 3.00k]
  ------------------
  100|  9.04k|    {
  101|  9.04k|      result.is_real = true;
  102|  9.04k|      ++i;  // consume '.'
  103|  26.4M|      while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (103:13): [True: 26.4M, False: 181]
  |  Branch (103:24): [True: 26.4M, False: 8.86k]
  ------------------
  104|  26.4M|      {
  105|  26.4M|        ++i;
  106|  26.4M|      }
  107|  9.04k|    }
  108|  3.01k|    else
  109|  3.01k|    {
  110|       |      // "65." or "65.x" -- incomplete real
  111|  3.01k|      result.has_error = true;
  112|  3.01k|      ++i;  // consume the dot
  113|  3.01k|      consumeTrailingGarbage(source, len, i);
  114|  3.01k|    }
  115|  22.1k|  }
  116|       |  // Exponent (only for decimal numbers)
  117|  4.62M|  if(!result.has_error && i < len && (source[i] == 'e' || source[i] == 'E'))
  ------------------
  |  Branch (117:6): [True: 4.61M, False: 3.01k]
  |  Branch (117:27): [True: 4.61M, False: 2.50k]
  |  Branch (117:39): [True: 7.28k, False: 4.60M]
  |  Branch (117:59): [True: 20.7k, False: 4.58M]
  ------------------
  118|  28.0k|  {
  119|  28.0k|    result.is_real = true;
  120|  28.0k|    ++i;  // consume 'e'/'E'
  121|  28.0k|    if(i < len && (source[i] == '+' || source[i] == '-'))
  ------------------
  |  Branch (121:8): [True: 28.0k, False: 33]
  |  Branch (121:20): [True: 1.08k, False: 26.9k]
  |  Branch (121:40): [True: 828, False: 26.1k]
  ------------------
  122|  1.91k|    {
  123|  1.91k|      ++i;  // consume sign
  124|  1.91k|    }
  125|  28.0k|    if(i >= len || !isDigit(source[i]))
  ------------------
  |  Branch (125:8): [True: 75, False: 27.9k]
  |  Branch (125:20): [True: 6.81k, False: 21.1k]
  ------------------
  126|  6.88k|    {
  127|  6.88k|      result.has_error = true;
  128|  6.88k|    }
  129|  21.1k|    else
  130|  21.1k|    {
  131|  1.92M|      while(i < len && isDigit(source[i]))
  ------------------
  |  Branch (131:13): [True: 1.91M, False: 263]
  |  Branch (131:24): [True: 1.89M, False: 20.8k]
  ------------------
  132|  1.89M|      {
  133|  1.89M|        ++i;
  134|  1.89M|      }
  135|  21.1k|    }
  136|  28.0k|  }
  137|       |  // Trailing alpha (e.g. "3foo", "65.43foo")
  138|  4.62M|  if(!result.has_error && i < len && isIdentStart(source[i]))
  ------------------
  |  Branch (138:6): [True: 4.61M, False: 9.90k]
  |  Branch (138:27): [True: 4.60M, False: 2.77k]
  |  Branch (138:38): [True: 324k, False: 4.28M]
  ------------------
  139|   324k|  {
  140|   324k|    result.has_error = true;
  141|  2.53M|    while(i < len && isIdentChar(source[i]))
  ------------------
  |  Branch (141:11): [True: 2.53M, False: 87]
  |  Branch (141:22): [True: 2.21M, False: 324k]
  ------------------
  142|  2.21M|    {
  143|  2.21M|      ++i;
  144|  2.21M|    }
  145|   324k|  }
  146|  4.62M|  return result;
  147|  4.62M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_112isIdentStartEc:
   24|  45.4M|{
   25|  45.4M|  return std::isalpha(static_cast<unsigned char>(c)) != 0 || c == '_' || c == '@';
  ------------------
  |  Branch (25:10): [True: 1.52M, False: 43.9M]
  |  Branch (25:62): [True: 36.0k, False: 43.8M]
  |  Branch (25:74): [True: 9.42M, False: 34.4M]
  ------------------
   26|  45.4M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_111isIdentCharEc:
   29|  62.6M|{
   30|  62.6M|  return std::isalnum(static_cast<unsigned char>(c)) != 0 || c == '_';
  ------------------
  |  Branch (30:10): [True: 51.5M, False: 11.0M]
  |  Branch (30:62): [True: 55.4k, False: 11.0M]
  ------------------
   31|  62.6M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_114matchTwoCharOpEcc:
  150|  30.1M|{
  151|  30.1M|  if(c == '.' && next == '.')
  ------------------
  |  Branch (151:6): [True: 67.0k, False: 30.0M]
  |  Branch (151:18): [True: 32.0k, False: 35.0k]
  ------------------
  152|  32.0k|    return TokenType::DotDot;
  153|  30.1M|  if(c == '&' && next == '&')
  ------------------
  |  Branch (153:6): [True: 20.2k, False: 30.1M]
  |  Branch (153:18): [True: 16.1k, False: 4.17k]
  ------------------
  154|  16.1k|    return TokenType::AmpAmp;
  155|  30.1M|  if(c == '|' && next == '|')
  ------------------
  |  Branch (155:6): [True: 64.4k, False: 30.0M]
  |  Branch (155:18): [True: 7.36k, False: 57.0k]
  ------------------
  156|  7.36k|    return TokenType::PipePipe;
  157|  30.1M|  if(c == '=' && next == '=')
  ------------------
  |  Branch (157:6): [True: 61.1k, False: 30.0M]
  |  Branch (157:18): [True: 12.8k, False: 48.2k]
  ------------------
  158|  12.8k|    return TokenType::EqualEqual;
  159|  30.0M|  if(c == '!' && next == '=')
  ------------------
  |  Branch (159:6): [True: 104k, False: 29.9M]
  |  Branch (159:18): [True: 69.5k, False: 34.5k]
  ------------------
  160|  69.5k|    return TokenType::BangEqual;
  161|  30.0M|  if(c == '<' && next == '=')
  ------------------
  |  Branch (161:6): [True: 432k, False: 29.5M]
  |  Branch (161:18): [True: 19.3k, False: 413k]
  ------------------
  162|  19.3k|    return TokenType::LessEqual;
  163|  29.9M|  if(c == '>' && next == '=')
  ------------------
  |  Branch (163:6): [True: 3.08M, False: 26.9M]
  |  Branch (163:18): [True: 28.1k, False: 3.05M]
  ------------------
  164|  28.1k|    return TokenType::GreaterEqual;
  165|  29.9M|  if(c == ':' && next == '=')
  ------------------
  |  Branch (165:6): [True: 64.2k, False: 29.9M]
  |  Branch (165:18): [True: 44.8k, False: 19.4k]
  ------------------
  166|  44.8k|    return TokenType::ColonEqual;
  167|  29.9M|  if(c == '+' && next == '=')
  ------------------
  |  Branch (167:6): [True: 46.6k, False: 29.8M]
  |  Branch (167:18): [True: 20.9k, False: 25.7k]
  ------------------
  168|  20.9k|    return TokenType::PlusEqual;
  169|  29.9M|  if(c == '-' && next == '=')
  ------------------
  |  Branch (169:6): [True: 246k, False: 29.6M]
  |  Branch (169:18): [True: 2.60k, False: 243k]
  ------------------
  170|  2.60k|    return TokenType::MinusEqual;
  171|  29.9M|  if(c == '*' && next == '=')
  ------------------
  |  Branch (171:6): [True: 7.04k, False: 29.8M]
  |  Branch (171:18): [True: 2.89k, False: 4.15k]
  ------------------
  172|  2.89k|    return TokenType::StarEqual;
  173|  29.9M|  if(c == '/' && next == '=')
  ------------------
  |  Branch (173:6): [True: 27.9k, False: 29.8M]
  |  Branch (173:18): [True: 3.29k, False: 24.6k]
  ------------------
  174|  3.29k|    return TokenType::SlashEqual;
  175|  29.8M|  return TokenType::Error;
  176|  29.9M|}
script_tokenizer.cpp:_ZN2BT9Scripting12_GLOBAL__N_117matchSingleCharOpEc:
  179|  29.8M|{
  180|  29.8M|  switch(c)
  181|  29.8M|  {
  182|  25.7k|    case '+':
  ------------------
  |  Branch (182:5): [True: 25.7k, False: 29.8M]
  ------------------
  183|  25.7k|      return TokenType::Plus;
  184|   243k|    case '-':
  ------------------
  |  Branch (184:5): [True: 243k, False: 29.6M]
  ------------------
  185|   243k|      return TokenType::Minus;
  186|  4.18k|    case '*':
  ------------------
  |  Branch (186:5): [True: 4.18k, False: 29.8M]
  ------------------
  187|  4.18k|      return TokenType::Star;
  188|  24.6k|    case '/':
  ------------------
  |  Branch (188:5): [True: 24.6k, False: 29.8M]
  ------------------
  189|  24.6k|      return TokenType::Slash;
  190|  4.25k|    case '&':
  ------------------
  |  Branch (190:5): [True: 4.25k, False: 29.8M]
  ------------------
  191|  4.25k|      return TokenType::Ampersand;
  192|  57.1k|    case '|':
  ------------------
  |  Branch (192:5): [True: 57.1k, False: 29.8M]
  ------------------
  193|  57.1k|      return TokenType::Pipe;
  194|  5.01k|    case '^':
  ------------------
  |  Branch (194:5): [True: 5.01k, False: 29.8M]
  ------------------
  195|  5.01k|      return TokenType::Caret;
  196|   134k|    case '~':
  ------------------
  |  Branch (196:5): [True: 134k, False: 29.7M]
  ------------------
  197|   134k|      return TokenType::Tilde;
  198|  34.5k|    case '!':
  ------------------
  |  Branch (198:5): [True: 34.5k, False: 29.8M]
  ------------------
  199|  34.5k|      return TokenType::Bang;
  200|   413k|    case '<':
  ------------------
  |  Branch (200:5): [True: 413k, False: 29.4M]
  ------------------
  201|   413k|      return TokenType::Less;
  202|  3.05M|    case '>':
  ------------------
  |  Branch (202:5): [True: 3.05M, False: 26.8M]
  ------------------
  203|  3.05M|      return TokenType::Greater;
  204|  48.3k|    case '=':
  ------------------
  |  Branch (204:5): [True: 48.3k, False: 29.8M]
  ------------------
  205|  48.3k|      return TokenType::Equal;
  206|  31.2k|    case '?':
  ------------------
  |  Branch (206:5): [True: 31.2k, False: 29.8M]
  ------------------
  207|  31.2k|      return TokenType::Question;
  208|  19.5k|    case ':':
  ------------------
  |  Branch (208:5): [True: 19.5k, False: 29.8M]
  ------------------
  209|  19.5k|      return TokenType::Colon;
  210|   189k|    case '(':
  ------------------
  |  Branch (210:5): [True: 189k, False: 29.7M]
  ------------------
  211|   189k|      return TokenType::LeftParen;
  212|  11.0k|    case ')':
  ------------------
  |  Branch (212:5): [True: 11.0k, False: 29.8M]
  ------------------
  213|  11.0k|      return TokenType::RightParen;
  214|  79.6k|    case ';':
  ------------------
  |  Branch (214:5): [True: 79.6k, False: 29.8M]
  ------------------
  215|  79.6k|      return TokenType::Semicolon;
  216|  25.5M|    default:
  ------------------
  |  Branch (216:5): [True: 25.5M, False: 4.37M]
  ------------------
  217|  25.5M|      return TokenType::Error;
  218|  29.8M|  }
  219|  29.8M|}

