28 #define DBG_SF LOG_STREAM(debug, log_scripting_formula)
29 #define LOG_SF LOG_STREAM(info, log_scripting_formula)
30 #define WRN_SF LOG_STREAM(warn, log_scripting_formula)
31 #define ERR_SF LOG_STREAM(err, log_scripting_formula)
39 const auto null_value = std::make_shared<variant_value_base>();
41 std::string get_debug_description(
const variant& v)
47 std::string was_expecting(
const std::string& expected,
const std::string& description)
49 return formatter{} <<
"TYPE ERROR: expected " << expected <<
" but found " << description;
53 std::string was_expecting(
const std::string& expected,
const variant& v)
55 return was_expecting(expected, get_debug_description(v));
61 if(v1.type() !=
t || v2.type() !=
t) {
67 << get_debug_description(v1) <<
", "
68 << get_debug_description(v2);
70 throw type_error{was_expecting(expected, provided)};
79 auto res = std::dynamic_pointer_cast<T>(v.
value_);
100 : type_(value->get_type())
228 return value_->get_type();
239 }
catch(
const std::out_of_range&) {
253 auto i = map.find(v);
261 std::vector<variant> slice;
263 slice.push_back((*
this)[v[
i]]);
266 return variant(std::move(slice));
267 }
else if(v.
as_int() < 0) {
274 throw type_error(was_expecting(
"a list or a map", *
this));
279 std::vector<variant> tmp;
280 for(
const auto& [key, value] :
as_map()) {
284 return variant(std::move(tmp));
289 std::vector<variant> tmp;
290 for(
const auto& [key, value] :
as_map()) {
291 tmp.push_back(value);
294 return variant(std::move(tmp));
299 return value_->make_iterator().begin();
304 return value_->make_iterator().end();
309 return value_->is_empty();
315 throw type_error(was_expecting(
"a list or a map", *
this));
318 return value_->num_elements();
325 return obj->query_value(name);
338 if(
is_null()) {
return fallback; }
341 return value_cast<variant_int>(*this)->get_numeric_value();
347 return value_cast<variant_decimal>(*this)->get_numeric_value();
349 return value_cast<variant_int>(*this)->get_numeric_value() * 1000;
354 throw type_error(was_expecting(
"an integer or a decimal", *
this));
364 return value_cast<variant_string>(*this)->get_string();
369 return value_cast<variant_list>(*this)->get_container();
374 return value_cast<variant_map>(*this)->get_container();
379 return value_cast<variant_callable>(*this)->get_callable();
389 std::map<variant, variant> res =
as_map();
391 for(
const auto& member : v.
as_map()) {
392 res[member.first] = member.second;
395 return variant(std::move(res));
424 if(long_int%10 >= 5) {
442 if(denominator == 0) {
443 throw type_error(
"decimal divide by zero error");
450 long_int /= denominator;
452 if(long_int%10 >= 5) {
462 const int numerator =
as_int();
463 const int denominator = v.
as_int();
465 if(denominator == 0) {
469 return variant(numerator / denominator);
477 if(denominator == 0) {
483 const int numerator =
as_int();
484 const int denominator = v.
as_int();
485 if(denominator == 0) {
489 return variant(numerator % denominator);
499 if(std::isnan(res)) {
506 return variant(
static_cast<int>(std::round(std::pow(
static_cast<double>(
as_int()), v.
as_int()))));
575 template<
typename Func>
578 must_both_be(formula_variant::type::list, v1, v2);
580 const std::vector<variant>& lhs = v1.
as_list();
581 const std::vector<variant>& rhs = v2.
as_list();
583 if(lhs.size() != rhs.size()) {
584 throw type_error(
"zip_transform requires two lists of the same length");
587 std::vector<variant> res;
588 res.reserve(lhs.size());
590 for(std::size_t
i = 0;
i < lhs.size(); ++
i) {
591 res.push_back(std::invoke(op_func, lhs[
i], rhs[
i]));
594 return variant(std::move(res));
599 must_both_be(formula_variant::type::list, v1, v2);
601 const std::vector<variant>& lhs = v1.
as_list();
602 const std::vector<variant>& rhs = v2.
as_list();
604 std::vector<variant> res;
605 res.reserve(lhs.size() + rhs.size());
607 std::copy(lhs.begin(), lhs.end(), std::back_inserter(res));
608 std::copy(rhs.begin(), rhs.end(), std::back_inserter(res));
610 return variant(std::move(res));
645 throw type_error(was_expecting(
"a list or a string", *
this));
650 must_both_be(formula_variant::type::integer, *
this, v);
651 return value_cast<variant_int>(*this)->build_range_variant(v.
as_int());
657 case formula_variant::type::list:
659 case formula_variant::type::map:
662 throw type_error(was_expecting(
"a list or a map", *
this));
668 return value_->get_serialized_string();
683 return value_->string_cast();
690 return value_->get_debug_string(seen_stack, verbose);
693 return value_->get_debug_string(*seen, verbose);
699 const auto to_execute = execute.
is_list()
703 std::vector<variant> res;
704 res.reserve(to_execute.size());
706 for(
const variant& v : to_execute) {
711 auto action = callable_cast<action_callable*>(v);
713 WRN_SF <<
"Could not execute non-action_callable variant: " << v.to_debug_string();
717 res.push_back(std::const_pointer_cast<action_callable>(action)->execute_self(context));
720 return variant(std::move(res));
std::unique_ptr< PangoAttribute, void(*)(PangoAttribute *)> value_
Iterator class for the variant.
bool operator!=(const variant_iterator &that) const
const variant_value_base * container_
variant operator*() const
bool operator==(const variant_iterator &that) const
variant_iterator & operator--()
variant_iterator()
Constructor for a no-op iterator.
variant_iterator & operator++()
Base class for all variant types.
virtual bool iterator_equals(const utils::any &, const utils::any &) const
Implements the equality functionality of variant_iterator for a value of this type.
virtual variant deref_iterator(const utils::any &iter) const
Implements the dereference functionality of variant_iterator for a value of this type.
virtual void iterator_dec(utils::any &) const
Implements the decrement functionality of variant_iterator for a value of this type.
virtual void iterator_inc(utils::any &) const
Implements the increment functionality of variant_iterator for a value of this type.
variant operator-() const
variant operator^(const variant &) const
variant concatenate(const variant &v) const
variant_iterator begin() const
std::shared_ptr< variant_value_base > value_
int as_int(int fallback=0) const
Returns the variant's value as an integer.
variant operator/(const variant &) const
variant get_values() const
void serialize_from_string(const std::string &str)
int as_decimal(int fallback=0) const
Returns the variant's internal representation of decimal number: ie, 1.234 is represented as 1234.
const_formula_callable_ptr as_callable() const
bool operator>=(const variant &) const
std::size_t num_elements() const
formula_variant::type type() const
bool operator!=(const variant &) const
variant operator+(const variant &) const
bool contains(const variant &other) const
bool operator==(const variant &) const
bool operator>(const variant &) const
variant operator*(const variant &) const
variant get_member(const std::string &name) const
variant list_elements_mul(const variant &v) const
std::string serialize_to_string() const
variant list_elements_add(const variant &v) const
const std::string & as_string() const
std::string string_cast() const
variant list_elements_div(const variant &v) const
variant_iterator end() const
bool as_bool() const
Returns a boolean state of the variant value.
bool operator<(const variant &) const
variant operator[](std::size_t n) const
variant build_range(const variant &v) const
variant operator%(const variant &) const
const std::vector< variant > & as_list() const
bool operator<=(const variant &) const
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
const std::map< variant, variant > & as_map() const
bool is_null() const
Functions to test the type of the internal value.
variant list_elements_sub(const variant &v) const
Standard logging facilities (interface).
Contains the implementation details for lexical_cast and shouldn't be used directly.
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
variant zip_transform(const variant &v1, const variant &v2, const Func &op_func)
Applies the provided function to the corresponding variants in both lists.
variant concat_lists(const variant &v1, const variant &v2)
std::vector< const_formula_callable_ptr > formula_seen_stack
std::shared_ptr< const formula_callable > const_formula_callable_ptr
std::shared_ptr< T > value_cast(const variant &v)
variant execute_actions(const variant &execute, const variant &context)
Executes all action_callables in execute using the provided context.
The base template for associating string values with enum values.
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
type_error(const std::string &str)
static map_location::direction n
static lg::log_domain log_scripting_formula("scripting/formula")