OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::client::MyContext Struct Reference
Inheritance diagram for Slic3r::client::MyContext:
Collaboration diagram for Slic3r::client::MyContext:

Classes

struct  NewOldVariable

Public Member Functions

size_t get_extruder_id () const
bool skipping () const
bool check_inactive_names () const
const ConfigOption * optptr (const t_config_option_key &opt_key) const override
const ConfigOption * resolve_symbol (const std::string &opt_key) const
ConfigOption * resolve_output_symbol (const std::string &opt_key) const
void store_new_variable (const std::string &opt_key, std::unique_ptr< ConfigOption > &&opt, bool global_variable)
void mark_deferred (expr &output) const
bool has (const t_config_option_key &opt_key) const
const ConfigOption * option (const t_config_option_key &opt_key) const
template<typename TYPE>
const TYPE * option (const t_config_option_key &opt_key) const
const ConfigOption * option_throw (const t_config_option_key &opt_key) const
template<typename TYPE>
const TYPE * option_throw (const t_config_option_key &opt_key) const

Static Public Member Functions

static bool evaluate_full_macro (const MyContext *ctx)
static void block_enter (const MyContext *ctx, const bool condition)
static void block_exit (const MyContext *ctx, const bool condition, bool &not_yet_consumed, std::string &data_in, std::string &data_out)
static void block_exit_ternary (const MyContext *ctx, const bool condition, expr &data_in, expr &data_out)
static void legacy_variable_expansion (const MyContext *ctx, IteratorRange &opt_key, std::string &output)
static void legacy_variable_expansion2 (const MyContext *ctx, IteratorRange &opt_key, IteratorRange &opt_vector_index, std::string &output)
static void resolve_variable (const MyContext *ctx, IteratorRange &opt_key, OptWithPos &output)
static void store_variable_index (const MyContext *ctx, OptWithPos &opt, int index, Iterator it_end, OptWithPos &output)
static void scalar_variable_to_expr (const MyContext *ctx, OptWithPos &opt, expr &output)
static void vector_element_to_expr (const MyContext *ctx, OptWithPos &opt, expr &output)
static void check_writable (const MyContext *ctx, OptWithPos &opt)
static void check_numeric (const expr &param)
static size_t evaluate_count (const expr &expr_count)
static void scalar_variable_assign_scalar (const MyContext *ctx, OptWithPos &lhs, const expr &rhs)
static void vector_variable_element_assign_scalar (const MyContext *ctx, OptWithPos &lhs, const expr &rhs)
static void vector_variable_assign_expr_with_count (const MyContext *ctx, OptWithPos &lhs, const expr &rhs_count, const expr &rhs_value)
static void variable_value (const MyContext *ctx, OptWithPos &opt, expr &output)
static void is_nil_test (const MyContext *ctx, OptWithPos &opt, expr &output)
static void new_old_variable (const MyContext *ctx, bool global_variable, const IteratorRange &it_range, NewOldVariable &out)
static void scalar_variable_assign_scalar_expression (const MyContext *ctx, OptWithPos &opt, const expr &param)
static void scalar_variable_new_from_scalar_expression (const MyContext *ctx, bool global_variable, NewOldVariable &lhs, const expr &rhs)
static void vector_variable_new_from_array (const MyContext *ctx, bool global_variable, NewOldVariable &lhs, const expr &rhs_count, const expr &rhs_value)
static void vector_variable_assign_array (const MyContext *ctx, OptWithPos &lhs, const expr &rhs_count, const expr &rhs_value)
template<typename ConfigOptionType, typename RightValueEvaluate>
static void fill_vector_from_initializer_list (ConfigOption *opt, const std::vector< expr > &il, RightValueEvaluate rv_eval)
static void vector_variable_assign_initializer_list (const MyContext *ctx, OptWithPos &lhs, const std::vector< expr > &il)
static void vector_variable_new_from_initializer_list (const MyContext *ctx, bool global_variable, NewOldVariable &lhs, const std::vector< expr > &il)
static bool is_vector_variable_reference (const OptWithPos &var)
static bool could_be_vector_variable_reference (const NewOldVariable &var)
static void copy_vector_variable_to_vector_variable (const MyContext *ctx, OptWithPos &lhs, const OptWithPos &rhs)
static bool vector_variable_new_from_copy (const MyContext *ctx, bool global_variable, NewOldVariable &lhs, const OptWithPos &rhs)
static void initializer_list_append (std::vector< expr > &list, expr &param)
static void is_vector_empty (const MyContext *ctx, OptWithPos &opt, expr &out)
static void vector_size (const MyContext *ctx, OptWithPos &opt, expr &out)
static void evaluate_index (expr &expr_index, int &output)
static void random (const MyContext *ctx, expr &param1, expr &param2)
static void filament_change (const MyContext *ctx, expr &param)
static void regex_replace (const MyContext *ctx, expr &subject, IteratorRange &pattern, expr &replacement)
static void throw_exception (const std::string &msg, const IteratorRange &it_range)
static void process_error_message (const MyContext *context, const boost::spirit::info &info, const Iterator &it_begin, const Iterator &it_end, const Iterator &it_error)

Public Attributes

const DynamicConfig * external_config = nullptr
const DynamicConfig * config = nullptr
const DynamicConfig * config_override = nullptr
DynamicConfig * config_outputs = nullptr
DynamicConfig config_local
size_t current_extruder_id = 0
PlaceholderParser::ContextData * context_data = nullptr
bool just_boolean_expression = false
std::string error_message
std::set< std::string > inactive_local_variables
const std::set< std::string > * deferred_tags = nullptr

Static Public Attributes

static std::map< std::string, std::string > tag_to_error_message

Private Attributes

int m_depth_suppressed { 0 }

Detailed Description


Class Documentation

◆ Slic3r::client::MyContext::NewOldVariable

struct Slic3r::client::MyContext::NewOldVariable
Collaboration diagram for Slic3r::client::MyContext::NewOldVariable:
Class Members
IteratorRange it_range
string name
ConfigOption * opt { nullptr }

Member Function Documentation

◆ block_enter()

void Slic3r::client::MyContext::block_enter ( const MyContext * ctx,
const bool condition )
inlinestatic
964 {
965 if (ctx->skipping() || ! condition)
966 ++ ctx->m_depth_suppressed;
967 }

References m_depth_suppressed, and skipping().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_exit()

void Slic3r::client::MyContext::block_exit ( const MyContext * ctx,
const bool condition,
bool & not_yet_consumed,
std::string & data_in,
std::string & data_out )
inlinestatic
970 {
971 if (ctx->skipping())
972 -- ctx->m_depth_suppressed;
973 else if (condition && not_yet_consumed) {
974 data_out = std::move(data_in);
975 not_yet_consumed = false;
976 }
977 }

References m_depth_suppressed, and skipping().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_exit_ternary()

void Slic3r::client::MyContext::block_exit_ternary ( const MyContext * ctx,
const bool condition,
expr & data_in,
expr & data_out )
inlinestatic
979 {
980 if (ctx->skipping())
981 -- ctx->m_depth_suppressed;
982 else if (condition)
983 data_out = std::move(data_in);
984 }

References m_depth_suppressed, and skipping().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_inactive_names()

bool Slic3r::client::MyContext::check_inactive_names ( ) const
inline
static bool check_inactive_branches
Definition PlaceholderParser.hpp:37
bool just_boolean_expression
Definition PlaceholderParser.cpp:940

References Slic3r::PlaceholderParser::check_inactive_branches, and just_boolean_expression.

Referenced by legacy_variable_expansion(), legacy_variable_expansion2(), new_old_variable(), and resolve_variable().

Here is the caller graph for this function:

◆ check_numeric()

void Slic3r::client::MyContext::check_numeric ( const expr & param)
inlinestatic
1376 {
1377 if (! param.numeric_type())
1378 param.throw_exception(L("Right side is not a numeric expression"));
1379 };
#define L(s)
Definition ExtrusionEntity.cpp:25

References L, Slic3r::client::expr::numeric_type(), and Slic3r::client::expr::throw_exception().

Referenced by scalar_variable_assign_scalar(), vector_variable_assign_expr_with_count(), and vector_variable_element_assign_scalar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_writable()

void Slic3r::client::MyContext::check_writable ( const MyContext * ctx,
OptWithPos & opt )
inlinestatic
1371 {
1372 if (! opt.writable)
1373 ctx->throw_exception(L("Cannot modify a read-only variable"), opt.it_range);
1374 }

References L, and throw_exception().

Referenced by copy_vector_variable_to_vector_variable(), scalar_variable_assign_scalar(), scalar_variable_assign_scalar_expression(), vector_variable_assign_array(), vector_variable_assign_initializer_list(), and vector_variable_element_assign_scalar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_vector_variable_to_vector_variable()

void Slic3r::client::MyContext::copy_vector_variable_to_vector_variable ( const MyContext * ctx,
OptWithPos & lhs,
const OptWithPos & rhs )
inlinestatic
1754 {
1755 if (ctx->skipping())
1756 return;
1757
1758 check_writable(ctx, lhs);
1759 assert(lhs.opt->is_vector());
1760 if (rhs.has_index() || ! rhs.opt->is_vector())
1761 ctx->throw_exception(L("Cannot assign scalar to a vector"), lhs.it_range);
1762 if (rhs.opt->is_nil())
1763 ctx->throw_exception(L("Some elements of the right hand side vector variable of optional values are undefined (nil)"), rhs.it_range);
1764 if (lhs.opt->type() != rhs.opt->type()) {
1765 // Vector types are not compatible.
1766 switch (lhs.opt->type()) {
1767 case coFloats:
1768 ctx->throw_exception(L("Left hand side is a float vector, while the right hand side is not."), lhs.it_range);
1769 case coInts:
1770 ctx->throw_exception(L("Left hand side is an int vector, while the right hand side is not."), lhs.it_range);
1771 case coStrings:
1772 ctx->throw_exception(L("Left hand side is a string vector, while the right hand side is not."), lhs.it_range);
1773 case coBools:
1774 ctx->throw_exception(L("Left hand side is a bool vector, while the right hand side is not."), lhs.it_range);
1775 default:
1776 ctx->throw_exception(L("Left hand side / right hand side vectors are not compatible."), lhs.it_range);
1777 }
1778 }
1779 const_cast<ConfigOption*>(lhs.opt)->set(rhs.opt);
1780 }
@ coBools
Definition Config.hpp:212
@ coInts
Definition Config.hpp:190
@ coStrings
Definition Config.hpp:194
@ coFloats
Definition Config.hpp:186
void set(id object, const void *key, id value)
Definition MacIME.mm:24
static void check_writable(const MyContext *ctx, OptWithPos &opt)
Definition PlaceholderParser.cpp:1371

References check_writable(), Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coStrings, Slic3r::client::OptWithPos::has_index(), Slic3r::ConfigOption::is_nil(), Slic3r::ConfigOption::is_vector(), Slic3r::client::OptWithPos::it_range, L, Slic3r::client::OptWithPos::opt, skipping(), throw_exception(), and Slic3r::ConfigOption::type().

Referenced by Slic3r::client::macro_processor::macro_processor(), and vector_variable_new_from_copy().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ could_be_vector_variable_reference()

bool Slic3r::client::MyContext::could_be_vector_variable_reference ( const NewOldVariable & var)
inlinestatic
1749 {
1750 return var.opt == nullptr || var.opt->is_vector();
1751 }
std::string var(const std::string &file_name)
Definition utils.cpp:278

References Slic3r::var().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ evaluate_count()

size_t Slic3r::client::MyContext::evaluate_count ( const expr & expr_count)
inlinestatic
1381 {
1382 if (expr_count.type() != expr::TYPE_INT)
1383 expr_count.throw_exception(L("Expected number of elements to fill a vector with."));
1384 int count = expr_count.i();
1385 if (count < 0)
1386 expr_count.throw_exception(L("Negative number of elements specified."));
1387 return size_t(count);
1388 };
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
@ TYPE_INT
Definition PlaceholderParser.cpp:308

References count, Slic3r::client::expr::i(), L, Slic3r::client::expr::throw_exception(), Slic3r::client::expr::type(), and Slic3r::client::expr::TYPE_INT.

Referenced by vector_variable_assign_expr_with_count(), and vector_variable_new_from_array().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ evaluate_full_macro()

bool Slic3r::client::MyContext::evaluate_full_macro ( const MyContext * ctx)
inlinestatic
960{ return ! ctx->just_boolean_expression; }

References just_boolean_expression.

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the caller graph for this function:

◆ evaluate_index()

void Slic3r::client::MyContext::evaluate_index ( expr & expr_index,
int & output )
inlinestatic
1846 {
1847 if (expr_index.type() != expr::TYPE_EMPTY) {
1848 if (expr_index.type() != expr::TYPE_INT)
1849 expr_index.throw_exception(L("Non-integer index is not allowed to address a vector variable."));
1850 output = expr_index.i();
1851 }
1852 }
@ TYPE_EMPTY
Definition PlaceholderParser.cpp:306

References Slic3r::client::expr::i(), L, Slic3r::client::expr::throw_exception(), Slic3r::client::expr::type(), Slic3r::client::expr::TYPE_EMPTY, and Slic3r::client::expr::TYPE_INT.

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ filament_change()

void Slic3r::client::MyContext::filament_change ( const MyContext * ctx,
expr & param )
inlinestatic
1866 {
1867 if (param.type() == expr::TYPE_EMPTY)
1868 // Inside an if / else block to be skipped
1869 return;
1870 MyContext *context = const_cast<MyContext *>(ctx);
1871 param.throw_if_deferred();
1872 context->current_extruder_id = param.as_i();
1873 }

References Slic3r::client::expr::as_i(), current_extruder_id, Slic3r::client::expr::throw_if_deferred(), Slic3r::client::expr::type(), and Slic3r::client::expr::TYPE_EMPTY.

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fill_vector_from_initializer_list()

template<typename ConfigOptionType, typename RightValueEvaluate>
void Slic3r::client::MyContext::fill_vector_from_initializer_list ( ConfigOption * opt,
const std::vector< expr > & il,
RightValueEvaluate rv_eval )
inlinestatic
1638 {
1639 auto& out = static_cast<ConfigOptionType*>(opt)->values;
1640 out.clear();
1641 out.reserve(il.size());
1642 for (const expr& i : il)
1643 out.emplace_back(rv_eval(i));
1644 }
ConfigOptionType
Definition Config.hpp:180

Referenced by vector_variable_assign_initializer_list().

Here is the caller graph for this function:

◆ get_extruder_id()

size_t Slic3r::client::MyContext::get_extruder_id ( ) const
inline
950 {
951 if (external_config != nullptr) {
952 const ConfigOptionInts * filament_map_opt = external_config->option<ConfigOptionInts>("filament_map");
953 if (filament_map_opt && current_extruder_id < filament_map_opt->values.size()) {
954 return filament_map_opt->values[current_extruder_id];
955 }
956 }
957 return 0;
958 }
ConfigOptionIntsTempl< false > ConfigOptionInts
Definition Config.hpp:1154
const DynamicConfig * external_config
Definition PlaceholderParser.cpp:925
size_t current_extruder_id
Definition PlaceholderParser.cpp:935

References current_extruder_id, external_config, Slic3r::ConfigOptionVector< int >::size(), and Slic3r::ConfigOptionVector< int >::values.

Referenced by vector_element_to_expr().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ has()

bool Slic3r::ConfigOptionResolver::has ( const t_config_option_key & opt_key) const
inlineinherited
2697{ return this->optptr(opt_key) != nullptr; }
virtual const ConfigOption * optptr(const t_config_option_key &opt_key) const =0

References optptr().

Referenced by Slic3r::_BBS_3MF_Exporter::_add_slice_info_config_file_to_archive(), Slic3r::active_bed_exclude_volume_mode(), Slic3r::append_bed_exclude_volumes(), Slic3r::append_printer_bed_assets(), Slic3r::GUI::change_opt_value(), Slic3r::GUI::ConfigManipulation::check_adaptive_pressure_advance_model(), Slic3r::GUI::PartPlateList::check_all_plate_local_bed_type(), Slic3r::GUI::ConfigManipulation::check_chamber_minimal_temperature(), Slic3r::GUI::ConfigManipulation::check_chamber_temperature(), Slic3r::GUI::ConfigManipulation::check_filament_max_volumetric_speed(), Slic3r::GUI::ConfigManipulation::check_nozzle_recommended_temperature_range(), Slic3r::GUI::ConfigManipulation::check_nozzle_temperature_initial_layer_range(), Slic3r::GUI::ConfigManipulation::check_nozzle_temperature_range(), Slic3r::config_value_or_none(), Slic3r::GUI::Bed3D::detect_type(), Slic3r::PresetCollection::dirty_options(), Slic3r::PresetCollection::dirty_options_without_option_list(), Slic3r::GUI::ensure_belt_purge_tower(), Slic3r::extend_default_config_length(), Slic3r::extend_extruder_variant(), Slic3r::anonymous_namespace{PluginResolver.cpp}::find_option_for_capability(), Slic3r::get_bed_excluded_regions_by_extruder(), Slic3r::GUI::PartPlate::get_bed_type(), Slic3r::anonymous_namespace{SL1.cpp}::get_cfg_value(), Slic3r::GUI::GLGizmoBrimEars::get_config_options(), Slic3r::GUI::ConfigOptionsGroup::get_config_value(), Slic3r::GUI::get_formatted_tooltip_text(), Slic3r::get_instance_arrange_poly(), Slic3r::GUI::PartPlate::get_object_filament_extruders(), Slic3r::GUI::OrientJob::get_orient_mesh(), Slic3r::DynamicPrintConfig::get_parameter_size(), Slic3r::GUI::CalibrationPresetPage::get_print_preset(), Slic3r::GUI::PartPlate::get_spiral_vase_mode(), Slic3r::GUI::ConfigManipulation::get_temperature_range(), Slic3r::GUI::PresetComboBox::get_tooltip(), Slic3r::PrintConfigDef::handle_legacy_composite(), Slic3r::handle_legacy_project_loaded(), Slic3r::handle_legacy_sla(), Slic3r::has_bed_exclude_volumes(), Slic3r::PresetBundle::import_json_presets(), Slic3r::PresetCollection::is_dirty(), Slic3r::GUI::is_same_nozzle_type(), Slic3r::GUI::ObjectList::load_shape_object(), Slic3r::PresetCollection::load_user_preset(), Slic3r::DynamicPrintConfig::normalize_fdm(), Slic3r::DynamicPrintConfig::normalize_fdm_1(), Slic3r::GUI::PartPlateList::notify_instance_update(), Slic3r::GUI::TabPrintPlate::on_value_change(), Slic3r::DynamicConfig::read_cli(), Slic3r::Preset::remove_invalid_keys(), Slic3r::GUI::PartPlate::render_logo(), Slic3r::PresetBundle::resolve_vendor_preset(), Slic3r::CLI::run(), Slic3r::GUI::PartPlate::set_bed_type(), Slic3r::set_filament_dev_options(), Slic3r::Model::setExtruderParams(), Slic3r::Model::setPrintSpeedTable(), Slic3r::GUI::TabFilament::toggle_options(), Slic3r::GUI::ConfigManipulation::toggle_print_fff_options(), Slic3r::GLVolumeCollection::update_colors_by_extruder(), Slic3r::PresetBundle::update_compatible(), Slic3r::GUI::TabPrintPlate::update_custom_dirty(), Slic3r::GUI::TabPrintModel::update_model_config(), Slic3r::GUI::ConfigManipulation::update_print_fff_config(), and Slic3r::GUI::Tab::validate_filament_temperature_pairs().

Here is the call graph for this function:

◆ initializer_list_append()

void Slic3r::client::MyContext::initializer_list_append ( std::vector< expr > & list,
expr & param )
inlinestatic
1817 {
1818 if (param.type() != expr::TYPE_EMPTY)
1819 // not skipping
1820 list.emplace_back(std::move(param));
1821 }

References Slic3r::client::expr::type(), and Slic3r::client::expr::TYPE_EMPTY.

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_nil_test()

void Slic3r::client::MyContext::is_nil_test ( const MyContext * ctx,
OptWithPos & opt,
expr & output )
inlinestatic
1501 {
1502 if (ctx->skipping()) {
1503 } else if (opt.opt->is_vector()) {
1504 if (! opt.has_index())
1505 ctx->throw_exception(L("Referencing a vector variable when scalar is expected"), opt.it_range);
1506 const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
1507 if (vec->empty())
1508 ctx->throw_exception(L("Indexing an empty vector variable"), opt.it_range);
1509 output.set_b(static_cast<const ConfigOptionVectorBase*>(opt.opt)->is_nil(opt.index >= int(vec->size()) ? 0 : size_t(opt.index)));
1510 } else {
1511 assert(opt.opt->is_scalar());
1512 output.set_b(opt.opt->is_nil());
1513 }
1514 output.it_range = opt.it_range;
1515 }

References Slic3r::ConfigOptionVectorBase::empty(), Slic3r::ConfigOptionVectorBase::is_nil(), Slic3r::client::expr::it_range, L, Slic3r::client::expr::set_b(), Slic3r::ConfigOptionVectorBase::size(), skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_vector_empty()

void Slic3r::client::MyContext::is_vector_empty ( const MyContext * ctx,
OptWithPos & opt,
expr & out )
inlinestatic
1824 {
1825 if (! ctx->skipping()) {
1826 if (opt.has_index() || ! opt.opt->is_vector())
1827 ctx->throw_exception(L("parameter of empty() is not a vector variable"), opt.it_range);
1828 out.set_b(static_cast<const ConfigOptionVectorBase*>(opt.opt)->size() == 0);
1829 }
1830 out.it_range = opt.it_range;
1831 }

References Slic3r::client::expr::it_range, L, Slic3r::client::expr::set_b(), Slic3r::ConfigOptionVectorBase::size(), skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_vector_variable_reference()

bool Slic3r::client::MyContext::is_vector_variable_reference ( const OptWithPos & var)
inlinestatic
1744 {
1745 return ! var.empty() && ! var.has_index() && var.opt->is_vector();
1746 }

References Slic3r::var().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ legacy_variable_expansion()

void Slic3r::client::MyContext::legacy_variable_expansion ( const MyContext * ctx,
IteratorRange & opt_key,
std::string & output )
inlinestatic
1035 {
1036 if (ctx->skipping() && ! ctx->check_inactive_names())
1037 return;
1038
1039 std::string opt_key_str(opt_key.begin(), opt_key.end());
1040 const ConfigOption *opt = ctx->resolve_symbol(opt_key_str);
1041 size_t idx = ctx->current_extruder_id;
1042 if (opt == nullptr) {
1043 // Check whether this is a legacy vector indexing.
1044 idx = opt_key_str.rfind('_');
1045 if (idx != std::string::npos) {
1046 opt = ctx->resolve_symbol(opt_key_str.substr(0, idx));
1047 if (opt != nullptr) {
1048 if (! opt->is_vector())
1049 ctx->throw_exception(L("Trying to index a scalar variable"), opt_key);
1050 char *endptr = nullptr;
1051 idx = strtol(opt_key_str.c_str() + idx + 1, &endptr, 10);
1052 if (endptr == nullptr || *endptr != 0)
1053 ctx->throw_exception(L("Invalid vector index"), IteratorRange(opt_key.begin() + idx + 1, opt_key.end()));
1054 }
1055 }
1056 }
1057 if (opt == nullptr)
1058 ctx->throw_exception(ctx->skipping() ? L("Variable does not exist (in an inactive branch)") : L("Variable does not exist"), opt_key);
1059 if (ctx->skipping())
1060 return;
1061 if (opt->is_scalar()) {
1062 if (opt->is_nil())
1063 ctx->throw_exception(L("Trying to reference an undefined (nil) optional variable"), opt_key);
1064 output = opt->serialize();
1065 } else {
1066 const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt);
1067 if (vec->empty())
1068 ctx->throw_exception(L("Indexing an empty vector variable"), opt_key);
1069 if (idx >= vec->size())
1070 idx = 0;
1071 if (vec->is_nil(idx))
1072 ctx->throw_exception(L("Trying to reference an undefined (nil) element of vector of optional values"), opt_key);
1073 output = vec->vserialize()[idx];
1074 }
1075 }
boost::iterator_range< Iterator > IteratorRange
Definition PlaceholderParser.cpp:222

References check_inactive_names(), current_extruder_id, Slic3r::ConfigOptionVectorBase::empty(), Slic3r::ConfigOptionVectorBase::is_nil(), L, resolve_symbol(), Slic3r::ConfigOptionVectorBase::size(), skipping(), throw_exception(), and Slic3r::ConfigOptionVectorBase::vserialize().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ legacy_variable_expansion2()

void Slic3r::client::MyContext::legacy_variable_expansion2 ( const MyContext * ctx,
IteratorRange & opt_key,
IteratorRange & opt_vector_index,
std::string & output )
inlinestatic
1082 {
1083 if (ctx->skipping() && ! ctx->check_inactive_names())
1084 return;
1085
1086 const char *not_found = ctx->skipping() ? L("Variable does not exist (in an inactive branch)") : L("Variable does not exist");
1087 std::string opt_key_str(opt_key.begin(), opt_key.end());
1088 const ConfigOption *opt = ctx->resolve_symbol(opt_key_str);
1089 if (opt == nullptr) {
1090 // Check whether the opt_key ends with '_'.
1091 if (opt_key_str.back() == '_') {
1092 opt_key_str.resize(opt_key_str.size() - 1);
1093 opt = ctx->resolve_symbol(opt_key_str);
1094 }
1095 if (opt == nullptr)
1096 ctx->throw_exception(not_found, opt_key);
1097 }
1098 if (! opt->is_vector())
1099 ctx->throw_exception(L("Trying to index a scalar variable"), opt_key);
1100 const ConfigOption *opt_index = ctx->resolve_symbol(std::string(opt_vector_index.begin(), opt_vector_index.end()));
1101 if (opt_index == nullptr)
1102 ctx->throw_exception(not_found, opt_key);
1103 if (opt_index->type() != coInt)
1104 ctx->throw_exception(L("Indexing variable has to be integer"), opt_key);
1105 if (ctx->skipping())
1106 return;
1107 const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt);
1108 if (vec->empty())
1109 ctx->throw_exception(L("Indexing an empty vector variable"), opt_key);
1110 int idx = opt_index->getInt();
1111 if (idx < 0)
1112 ctx->throw_exception(L("Negative vector index"), opt_key);
1113 if (idx >= (int)vec->size())
1114 idx = 0;
1115 if (vec->is_nil(idx))
1116 ctx->throw_exception(L("Trying to reference an undefined (nil) element of vector of optional values"), opt_key);
1117 output = vec->vserialize()[idx];
1118 }
@ coInt
Definition Config.hpp:188

References check_inactive_names(), Slic3r::coInt, Slic3r::ConfigOptionVectorBase::empty(), Slic3r::ConfigOption::getInt(), Slic3r::ConfigOptionVectorBase::is_nil(), L, resolve_symbol(), Slic3r::ConfigOptionVectorBase::size(), skipping(), throw_exception(), Slic3r::ConfigOption::type(), and Slic3r::ConfigOptionVectorBase::vserialize().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mark_deferred()

void Slic3r::client::MyContext::mark_deferred ( expr & output) const
inline
1021 {
1022 if (output.type() != expr::TYPE_STRING)
1023 return;
1025 if (deferred_tags != nullptr && output.s().find('@') != std::string::npos)
1026 for (const std::string &tag : *deferred_tags)
1027 if (output.s().find(tag) != std::string::npos) {
1028 deferred = output.s() == tag ? expr::Deferred::Value : expr::Deferred::Text;
1029 break;
1030 }
1031 output.set_deferred(deferred);
1032 }
const std::set< std::string > * deferred_tags
Definition PlaceholderParser.cpp:945
Deferred
Definition PlaceholderParser.cpp:315
@ Value
Definition PlaceholderParser.cpp:315
@ None
Definition PlaceholderParser.cpp:315
@ Text
Definition PlaceholderParser.cpp:315
@ TYPE_STRING
Definition PlaceholderParser.cpp:310

References deferred_tags, Slic3r::client::expr::None, Slic3r::client::expr::s(), Slic3r::client::expr::set_deferred(), Slic3r::client::expr::Text, Slic3r::client::expr::type(), Slic3r::client::expr::TYPE_STRING, and Slic3r::client::expr::Value.

Referenced by regex_replace(), and variable_value().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_old_variable()

void Slic3r::client::MyContext::new_old_variable ( const MyContext * ctx,
bool global_variable,
const IteratorRange & it_range,
NewOldVariable & out )
inlinestatic
1528 {
1529 if (! ctx->skipping()) {
1530 t_config_option_key key(std::string(it_range.begin(), it_range.end()));
1531 if (const ConfigOption* opt = ctx->resolve_symbol(key); opt)
1532 ctx->throw_exception(L("Symbol is already defined in read-only system dictionary"), it_range);
1533 if (ctx->config_outputs && ctx->config_outputs->optptr(key))
1534 ctx->throw_exception(L("Symbol is already defined as system output variable"), it_range);
1535 bool has_global_dictionary = ctx->context_data != nullptr && ctx->context_data->global_config;
1536 if (global_variable) {
1537 if (! has_global_dictionary)
1538 ctx->throw_exception(L("Global variables are not available in this context"), it_range);
1539 if (ctx->config_local.optptr(key))
1540 ctx->throw_exception(L("Variable name already defined in local scope"), it_range);
1541 out.opt = ctx->context_data->global_config->optptr(key);
1542 } else {
1543 if (has_global_dictionary && ctx->context_data->global_config->optptr(key))
1544 ctx->throw_exception(L("Variable name already defined in global scope"), it_range);
1545 out.opt = ctx->config_local.optptr(key);
1546 }
1547 out.name = std::move(key);
1548 } else if (ctx->check_inactive_names()) {
1549 // Declared in a branch that is not taken: the name still counts as defined for the names that follow.
1550 std::string key(it_range.begin(), it_range.end());
1551 if (global_variable && ctx->context_data != nullptr)
1552 ctx->context_data->inactive_global_variables.insert(std::move(key));
1553 else
1554 ctx->inactive_local_variables.insert(std::move(key));
1555 }
1556 out.it_range = it_range;
1557 }
std::string t_config_option_key
Definition Config.hpp:96

References check_inactive_names(), config_local, config_outputs, context_data, Slic3r::PlaceholderParser::ContextData::global_config, Slic3r::PlaceholderParser::ContextData::inactive_global_variables, inactive_local_variables, Slic3r::client::MyContext::NewOldVariable::it_range, L, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::client::MyContext::NewOldVariable::opt, Slic3r::DynamicConfig::optptr(), resolve_symbol(), skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ option() [1/2]

template<typename TYPE>
const TYPE * Slic3r::ConfigOptionResolver::option ( const t_config_option_key & opt_key) const
inlineinherited
2703 {
2704 const ConfigOption* opt = this->optptr(opt_key);
2705 return (opt == nullptr || opt->type() != TYPE::static_type()) ? nullptr : static_cast<const TYPE*>(opt);
2706 }

References optptr().

Here is the call graph for this function:

◆ option() [2/2]

const ConfigOption * Slic3r::ConfigOptionResolver::option ( const t_config_option_key & opt_key) const
inlineinherited
2699{ return this->optptr(opt_key); }

References optptr().

Referenced by Slic3r::Flow::extrusion_width(), Slic3r::Flow::extrusion_width(), and Slic3r::PrintObject::invalidate_state_by_config_options().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ option_throw() [1/2]

template<typename TYPE>
const TYPE * Slic3r::ConfigOptionResolver::option_throw ( const t_config_option_key & opt_key) const
inlineinherited
2718 {
2719 const ConfigOption* opt = this->option_throw(opt_key);
2720 if (opt->type() != TYPE::static_type())
2721 throw BadOptionTypeException("Conversion to a wrong type");
2722 return static_cast<TYPE*>(opt);
2723 }
const ConfigOption * option_throw(const t_config_option_key &opt_key) const
Definition Config.hpp:2708

References option_throw().

Here is the call graph for this function:

◆ option_throw() [2/2]

const ConfigOption * Slic3r::ConfigOptionResolver::option_throw ( const t_config_option_key & opt_key) const
inlineinherited
2709 {
2710 const ConfigOption* opt = this->optptr(opt_key);
2711 if (opt == nullptr)
2712 throw UnknownOptionException(opt_key);
2713 return opt;
2714 }

References optptr().

Referenced by option_throw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ optptr()

const ConfigOption * Slic3r::client::MyContext::optptr ( const t_config_option_key & opt_key) const
inlineoverridevirtual

Implements Slic3r::ConfigOptionResolver.

991 {
992 const ConfigOption *opt = nullptr;
993 if (config_override != nullptr)
994 opt = config_override->option(opt_key);
995 if (opt == nullptr)
996 opt = config->option(opt_key);
997 if (opt == nullptr && external_config != nullptr)
998 opt = external_config->option(opt_key);
999 return opt;
1000 }
const DynamicConfig * config
Definition PlaceholderParser.cpp:927
const DynamicConfig * config_override
Definition PlaceholderParser.cpp:929

References config, config_override, and external_config.

Referenced by resolve_symbol().

Here is the caller graph for this function:

◆ process_error_message()

void Slic3r::client::MyContext::process_error_message ( const MyContext * context,
const boost::spirit::info & info,
const Iterator & it_begin,
const Iterator & it_end,
const Iterator & it_error )
inlinestatic
1890 {
1891 std::string &msg = const_cast<MyContext*>(context)->error_message;
1892 std::string first(it_begin, it_error);
1893 std::string last(it_error, it_end);
1894 auto first_pos = first.rfind('\n');
1895 auto last_pos = last.find('\n');
1896 int line_nr = 1;
1897 if (first_pos == std::string::npos)
1898 first_pos = 0;
1899 else {
1900 // Calculate the current line number.
1901 for (size_t i = 0; i <= first_pos; ++ i)
1902 if (first[i] == '\n')
1903 ++ line_nr;
1904 ++ first_pos;
1905 }
1906 auto error_line = std::string(first, first_pos) + std::string(last, 0, last_pos);
1907 // Position of the it_error from the start of its line.
1908 auto error_pos = (it_error - it_begin) - first_pos;
1909 if (! info.tag.empty() && info.tag.front() == '*') {
1910 // The gat contains an explanatory string.
1911 // TRN Custom G-code error. %1% is the line number, %2% the reason.
1912 msg += Slic3r::format(_u8L("Parsing error at line %1%: %2%"), line_nr, Slic3r::I18N::translate(info.tag.substr(1)));
1913 } else {
1914 auto it = tag_to_error_message.find(info.tag);
1915 if (it == tag_to_error_message.end()) {
1916 // A generic error report based on the nonterminal or terminal symbol name.
1917 // TRN Custom G-code error. %1% is the line number, %2% the name of a grammar rule.
1918 msg += Slic3r::format(_u8L("Parsing error at line %1%. Expecting tag %2%"), line_nr, info.tag);
1919 } else {
1920 // Use the human readable error message.
1921 // TRN Custom G-code error. %1% is the line number, %2% the reason.
1922 msg += Slic3r::format(_u8L("Parsing error at line %1%. %2%"), line_nr, Slic3r::I18N::translate(it->second));
1923 }
1924 }
1925 msg += '\n';
1926 // This hack removes all non-UTF8 characters from the source line, so that the upstream wxWidgets conversions
1927 // from UTF8 to UTF16 don't bail out.
1928 msg += boost::nowide::narrow(boost::nowide::widen(error_line));
1929 msg += '\n';
1930 // The error dialog (MsgDialog.cpp) renders this excerpt monospaced. It recognizes a source
1931 // line directly above a caret line of spaces and a single '^'.
1932 for (size_t i = 0; i < error_pos; ++ i)
1933 msg += ' ';
1934 msg += "^\n";
1935 }
std::string translate(const std::string &s)
Definition I18N.hpp:18
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:45
#define _u8L(s)
Definition I18N.hpp:11
static std::map< std::string, std::string > tag_to_error_message
Definition PlaceholderParser.cpp:948
std::string error_message
Definition PlaceholderParser.cpp:941

References _u8L, error_message, Slic3r::format(), tag_to_error_message, and Slic3r::I18N::translate().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ random()

void Slic3r::client::MyContext::random ( const MyContext * ctx,
expr & param1,
expr & param2 )
inlinestatic
1855 {
1856 if (ctx->skipping())
1857 return;
1858
1859 if (ctx->context_data == nullptr)
1860 ctx->throw_exception(L("Random number generator not available in this context."),
1861 IteratorRange(param1.it_range.begin(), param2.it_range.end()));
1862 expr::random(param1, param2, ctx->context_data->rng);
1863 }
static void random(expr &param1, expr &param2, std::mt19937 &rng)
Definition PlaceholderParser.cpp:714

References context_data, Slic3r::client::expr::it_range, L, Slic3r::client::expr::random(), Slic3r::PlaceholderParser::ContextData::rng, skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ regex_replace()

void Slic3r::client::MyContext::regex_replace ( const MyContext * ctx,
expr & subject,
IteratorRange & pattern,
expr & replacement )
inlinestatic
1877 {
1878 expr::regex_replace(subject, pattern, replacement);
1879 ctx->mark_deferred(subject);
1880 }
static void regex_replace(expr &subject, IteratorRange &pattern, expr &replacement)
Definition PlaceholderParser.cpp:785

References mark_deferred(), and Slic3r::client::expr::regex_replace().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolve_output_symbol()

ConfigOption * Slic3r::client::MyContext::resolve_output_symbol ( const std::string & opt_key) const
inline
1003 {
1004 ConfigOption *out = nullptr;
1005 if (this->config_outputs)
1006 out = this->config_outputs->optptr(opt_key, false);
1007 if (out == nullptr && this->context_data != nullptr && this->context_data->global_config)
1008 out = this->context_data->global_config->optptr(opt_key);
1009 if (out == nullptr)
1010 out = this->config_local.optptr(opt_key);
1011 return out;
1012 }
DynamicConfig config_local
Definition PlaceholderParser.cpp:934
DynamicConfig * config_outputs
Definition PlaceholderParser.cpp:932
PlaceholderParser::ContextData * context_data
Definition PlaceholderParser.cpp:937

References Slic3r::PlaceholderParser::ContextData::global_config, and Slic3r::DynamicConfig::optptr().

Referenced by resolve_variable().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolve_symbol()

const ConfigOption * Slic3r::client::MyContext::resolve_symbol ( const std::string & opt_key) const
inline
1002{ return this->optptr(opt_key); }
const ConfigOption * optptr(const t_config_option_key &opt_key) const override
Definition PlaceholderParser.cpp:990

References optptr().

Referenced by legacy_variable_expansion(), legacy_variable_expansion2(), new_old_variable(), resolve_variable(), scalar_variable_to_expr(), and vector_element_to_expr().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolve_variable()

void Slic3r::client::MyContext::resolve_variable ( const MyContext * ctx,
IteratorRange & opt_key,
OptWithPos & output )
inlinestatic
1124 {
1125 if (! ctx->skipping()) {
1126 const std::string key{ opt_key.begin(), opt_key.end() };
1127 const ConfigOption *opt = ctx->resolve_symbol(key);
1128 if (opt == nullptr) {
1129 opt = ctx->resolve_output_symbol(key);
1130 if (opt == nullptr)
1131 ctx->throw_exception(L("Not a variable name"), opt_key);
1132 output.writable = true;
1133 }
1134 output.opt = opt;
1135 } else if (ctx->check_inactive_names()) {
1136 // Only check the name. Back tracking may resolve the same identifier twice, so there are no side effects.
1137 const std::string key{ opt_key.begin(), opt_key.end() };
1138 if (ctx->resolve_symbol(key) == nullptr && ctx->resolve_output_symbol(key) == nullptr &&
1139 ctx->inactive_local_variables.count(key) == 0 &&
1140 (ctx->context_data == nullptr || ctx->context_data->inactive_global_variables.count(key) == 0))
1141 ctx->throw_exception(L("Not a variable name (in an inactive branch)"), opt_key);
1142 }
1143 output.it_range = opt_key;
1144 }

References check_inactive_names(), context_data, Slic3r::PlaceholderParser::ContextData::inactive_global_variables, inactive_local_variables, Slic3r::client::OptWithPos::it_range, L, Slic3r::client::OptWithPos::opt, resolve_output_symbol(), resolve_symbol(), skipping(), throw_exception(), and Slic3r::client::OptWithPos::writable.

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ scalar_variable_assign_scalar()

void Slic3r::client::MyContext::scalar_variable_assign_scalar ( const MyContext * ctx,
OptWithPos & lhs,
const expr & rhs )
inlinestatic
1391 {
1392 assert(! ctx->skipping());
1393 assert(lhs.opt->is_scalar());
1394 check_writable(ctx, lhs);
1395 ConfigOption *wropt = const_cast<ConfigOption*>(lhs.opt);
1396 switch (wropt->type()) {
1397 case coFloat:
1398 check_numeric(rhs);
1399 static_cast<ConfigOptionFloat*>(wropt)->value = rhs.as_d();
1400 break;
1401 case coInt:
1402 check_numeric(rhs);
1403 static_cast<ConfigOptionInt*>(wropt)->value = rhs.as_i();
1404 break;
1405 case coString:
1406 static_cast<ConfigOptionString*>(wropt)->value = rhs.to_string();
1407 break;
1408 case coPercent:
1409 check_numeric(rhs);
1410 static_cast<ConfigOptionPercent*>(wropt)->value = rhs.as_d();
1411 break;
1412 case coBool:
1413 if (rhs.type() != expr::TYPE_BOOL)
1414 ctx->throw_exception(L("Right side is not a boolean expression"), rhs.it_range);
1415 static_cast<ConfigOptionBool*>(wropt)->value = rhs.b();
1416 break;
1417 default:
1418 ctx->throw_exception(L("Unsupported output scalar variable type"), lhs.it_range);
1419 }
1420 }
zaa_minimize_perimeter_height ConfigOptionFloat
Definition PrintConfig.hpp:1954
zaa_minimize_perimeter_height ConfigOptionString
Definition PrintConfig.hpp:1702
@ coString
Definition Config.hpp:192
@ coBool
Definition Config.hpp:210
@ coFloat
Definition Config.hpp:184
@ coPercent
Definition Config.hpp:196
static void check_numeric(const expr &param)
Definition PlaceholderParser.cpp:1376
@ TYPE_BOOL
Definition PlaceholderParser.cpp:307

References Slic3r::client::expr::as_d(), Slic3r::client::expr::as_i(), Slic3r::client::expr::b(), check_numeric(), check_writable(), Slic3r::coBool, Slic3r::coFloat, Slic3r::coInt, Slic3r::coPercent, Slic3r::coString, Slic3r::ConfigOption::is_scalar(), Slic3r::client::expr::it_range, Slic3r::client::OptWithPos::it_range, L, Slic3r::client::OptWithPos::opt, skipping(), throw_exception(), Slic3r::client::expr::to_string(), Slic3r::client::expr::type(), Slic3r::ConfigOption::type(), and Slic3r::client::expr::TYPE_BOOL.

Referenced by scalar_variable_assign_scalar_expression(), and scalar_variable_new_from_scalar_expression().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ scalar_variable_assign_scalar_expression()

void Slic3r::client::MyContext::scalar_variable_assign_scalar_expression ( const MyContext * ctx,
OptWithPos & opt,
const expr & param )
inlinestatic
1561 {
1562 if (! ctx->skipping()) {
1563 check_writable(ctx, opt);
1564 if (opt.opt->is_vector())
1566 else
1567 scalar_variable_assign_scalar(ctx, opt, param);
1568 }
1569 }
static void scalar_variable_assign_scalar(const MyContext *ctx, OptWithPos &lhs, const expr &rhs)
Definition PlaceholderParser.cpp:1390
static void vector_variable_element_assign_scalar(const MyContext *ctx, OptWithPos &lhs, const expr &rhs)
Definition PlaceholderParser.cpp:1422

References check_writable(), scalar_variable_assign_scalar(), skipping(), and vector_variable_element_assign_scalar().

Referenced by Slic3r::client::macro_processor::macro_processor(), and vector_variable_assign_initializer_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ scalar_variable_new_from_scalar_expression()

void Slic3r::client::MyContext::scalar_variable_new_from_scalar_expression ( const MyContext * ctx,
bool global_variable,
NewOldVariable & lhs,
const expr & rhs )
inlinestatic
1576 {
1577 if (ctx->skipping()) {
1578 } else if (lhs.opt) {
1579 if (lhs.opt->is_vector())
1580 ctx->throw_exception(L("Cannot assign a scalar value to a vector variable."), rhs.it_range);
1581 OptWithPos lhs_opt{ lhs.opt, lhs.it_range, true };
1582 scalar_variable_assign_scalar(ctx, lhs_opt, rhs);
1583 } else {
1584 std::unique_ptr<ConfigOption> opt_new;
1585 switch (rhs.type()) {
1586 case expr::TYPE_BOOL: opt_new = std::make_unique<ConfigOptionBool>(rhs.b()); break;
1587 case expr::TYPE_INT: opt_new = std::make_unique<ConfigOptionInt>(rhs.i()); break;
1588 case expr::TYPE_DOUBLE: opt_new = std::make_unique<ConfigOptionFloat>(rhs.d()); break;
1589 case expr::TYPE_STRING: opt_new = std::make_unique<ConfigOptionString>(rhs.s()); break;
1590 default: assert(false);
1591 }
1592 const_cast<MyContext*>(ctx)->store_new_variable(lhs.name, std::move(opt_new), global_variable);
1593 }
1594 }
void store_new_variable(const std::string &opt_key, std::unique_ptr< ConfigOption > &&opt, bool global_variable)
Definition PlaceholderParser.cpp:1013
@ TYPE_DOUBLE
Definition PlaceholderParser.cpp:309

References Slic3r::client::expr::b(), Slic3r::client::expr::d(), Slic3r::client::expr::i(), Slic3r::ConfigOption::is_vector(), Slic3r::client::expr::it_range, Slic3r::client::MyContext::NewOldVariable::it_range, L, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::client::MyContext::NewOldVariable::opt, Slic3r::client::expr::s(), scalar_variable_assign_scalar(), skipping(), store_new_variable(), throw_exception(), Slic3r::client::expr::type(), Slic3r::client::expr::TYPE_BOOL, Slic3r::client::expr::TYPE_DOUBLE, Slic3r::client::expr::TYPE_INT, and Slic3r::client::expr::TYPE_STRING.

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ scalar_variable_to_expr()

void Slic3r::client::MyContext::scalar_variable_to_expr ( const MyContext * ctx,
OptWithPos & opt,
expr & output )
inlinestatic
1168 {
1169 if (ctx->skipping())
1170 return;
1171
1172 assert(opt.opt->is_scalar());
1173
1174 if (opt.opt->is_nil())
1175 ctx->throw_exception(L("Trying to reference an undefined (nil) optional variable"), opt.it_range);
1176
1177 switch (opt.opt->type()) {
1178 case coFloat: output.set_d(opt.opt->getFloat()); break;
1179 case coInt: output.set_i(opt.opt->getInt()); break;
1180 case coString: output.set_s(static_cast<const ConfigOptionString*>(opt.opt)->value); break;
1181 case coPercent: output.set_d(opt.opt->getFloat()); break;
1182 case coEnum:
1183 case coPoint: output.set_s(opt.opt->serialize()); break;
1184 case coBool: output.set_b(opt.opt->getBool()); break;
1185 case coFloatOrPercent:
1186 {
1187 std::string opt_key(opt.it_range.begin(), opt.it_range.end());
1188 if (boost::ends_with(opt_key, "line_width")) {
1189 // Line width supports defaults and a complex graph of dependencies.
1190 output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast<unsigned int>(ctx->current_extruder_id)));
1191 } else if (! static_cast<const ConfigOptionFloatOrPercent*>(opt.opt)->percent) {
1192 // Not a percent, just return the value.
1193 output.set_d(opt.opt->getFloat());
1194 } else {
1195 // Resolve dependencies using the "ratio_over" link to a parent value.
1196 const ConfigOptionDef *opt_def = print_config_def.get(opt_key);
1197 assert(opt_def != nullptr);
1198 double v = opt.opt->getFloat() * 0.01; // percent to ratio
1199 for (;;) {
1200 const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over);
1201 if (opt_parent == nullptr)
1202 ctx->throw_exception(L("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies"), opt.it_range);
1203 if (boost::ends_with(opt_def->ratio_over, "line_width")) {
1204 // Line width supports defaults and a complex graph of dependencies.
1205 assert(opt_parent->type() == coFloatOrPercent);
1206 v *= Flow::extrusion_width(opt_def->ratio_over, static_cast<const ConfigOptionFloatOrPercent*>(opt_parent), *ctx, static_cast<unsigned int>(ctx->current_extruder_id));
1207 break;
1208 }
1209 if (opt_parent->type() == coFloat || opt_parent->type() == coFloatOrPercent) {
1210 v *= opt_parent->getFloat();
1211 if (opt_parent->type() == coFloat || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_parent)->percent)
1212 break;
1213 v *= 0.01; // percent to ratio
1214 }
1215 // Continue one level up in the "ratio_over" hierarchy.
1216 opt_def = print_config_def.get(opt_def->ratio_over);
1217 assert(opt_def != nullptr);
1218 }
1219 output.set_d(v);
1220 }
1221 break;
1222 }
1223 default:
1224 ctx->throw_exception(L("Unsupported scalar variable type"), opt.it_range);
1225 }
1226 }
const ConfigOptionDef * get(const t_config_option_key &opt_key) const
Definition Config.hpp:2662
static double extrusion_width(const std::string &opt_key, const ConfigOptionFloatOrPercent *opt, const ConfigOptionResolver &config, const unsigned int first_printing_extruder=0)
Definition Flow.cpp:75
const PrintConfigDef print_config_def
Definition PrintConfig.cpp:10099
@ coPoint
Definition Config.hpp:204
@ coEnum
Definition Config.hpp:214
@ coFloatOrPercent
Definition Config.hpp:200

References Slic3r::coBool, Slic3r::coEnum, Slic3r::coFloat, Slic3r::coFloatOrPercent, Slic3r::coInt, Slic3r::coPercent, Slic3r::coPoint, Slic3r::coString, current_extruder_id, Slic3r::Flow::extrusion_width(), Slic3r::ConfigOption::getFloat(), L, Slic3r::ConfigOptionFloatOrPercent::percent, Slic3r::print_config_def, Slic3r::ConfigOptionDef::ratio_over, resolve_symbol(), Slic3r::client::expr::set_b(), Slic3r::client::expr::set_d(), Slic3r::client::expr::set_i(), Slic3r::client::expr::set_s(), skipping(), throw_exception(), Slic3r::ConfigOption::type(), and Slic3r::ConfigOptionSingle< T >::value.

Referenced by variable_value().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ skipping()

◆ store_new_variable()

void Slic3r::client::MyContext::store_new_variable ( const std::string & opt_key,
std::unique_ptr< ConfigOption > && opt,
bool global_variable )
inline
1013 {
1014 assert(opt);
1015 if (global_variable) {
1016 assert(this->context_data != nullptr && this->context_data->global_config);
1017 this->context_data->global_config->set_key_value(opt_key, opt.release());
1018 } else
1019 this->config_local.set_key_value(opt_key, opt.release());
1020 }

References Slic3r::PlaceholderParser::ContextData::global_config, and Slic3r::DynamicConfig::set_key_value().

Referenced by scalar_variable_new_from_scalar_expression(), vector_variable_new_from_array(), vector_variable_new_from_copy(), and vector_variable_new_from_initializer_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ store_variable_index()

void Slic3r::client::MyContext::store_variable_index ( const MyContext * ctx,
OptWithPos & opt,
int index,
Iterator it_end,
OptWithPos & output )
inlinestatic
1152 {
1153 if (! ctx->skipping()) {
1154 if (index < 0)
1155 index = 0; // Orca: fallback to first element if index < 0, this matches the behavior of BambuStudio
1156 if (!opt.opt->is_vector())
1157 index = -1; // Orca: ignore the index if variable is scalar, this matches the behavior of BambuStudio
1158 output = opt;
1159 output.index = index;
1160 } else
1161 output = opt;
1162 output.it_range.end() = it_end;
1163 }

References Slic3r::client::OptWithPos::index, Slic3r::client::OptWithPos::it_range, and skipping().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ throw_exception()

void Slic3r::client::MyContext::throw_exception ( const std::string & msg,
const IteratorRange & it_range )
inlinestatic
1883 {
1884 // An asterix is added to the start of the string to differentiate the boost::spirit::info::tag content
1885 // between the grammer terminal / non-terminal symbol name and a free-form error message.
1886 boost::throw_exception(qi::expectation_failure(it_range.begin(), it_range.end(), spirit::info(std::string("*") + msg)));
1887 }

Referenced by check_writable(), copy_vector_variable_to_vector_variable(), is_nil_test(), is_vector_empty(), legacy_variable_expansion(), legacy_variable_expansion2(), new_old_variable(), Slic3r::client::ascii_char_skipper_parser::parse(), Slic3r::client::utf8_char_parser::parse(), random(), resolve_variable(), scalar_variable_assign_scalar(), scalar_variable_new_from_scalar_expression(), scalar_variable_to_expr(), Slic3r::client::FactorActions::string_(), vector_element_to_expr(), vector_size(), vector_variable_assign_array(), vector_variable_assign_initializer_list(), vector_variable_element_assign_scalar(), vector_variable_new_from_array(), vector_variable_new_from_copy(), and vector_variable_new_from_initializer_list().

Here is the caller graph for this function:

◆ variable_value()

void Slic3r::client::MyContext::variable_value ( const MyContext * ctx,
OptWithPos & opt,
expr & output )
inlinestatic
1487 {
1488 if (! ctx->skipping()) {
1489 if (opt.opt->is_vector())
1490 vector_element_to_expr(ctx, opt, output);
1491 else
1492 scalar_variable_to_expr(ctx, opt, output);
1493 ctx->mark_deferred(output);
1494 }
1495 output.it_range = opt.it_range;
1496 }
static void scalar_variable_to_expr(const MyContext *ctx, OptWithPos &opt, expr &output)
Definition PlaceholderParser.cpp:1167
static void vector_element_to_expr(const MyContext *ctx, OptWithPos &opt, expr &output)
Definition PlaceholderParser.cpp:1230

References Slic3r::client::expr::it_range, mark_deferred(), scalar_variable_to_expr(), skipping(), and vector_element_to_expr().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_element_to_expr()

void Slic3r::client::MyContext::vector_element_to_expr ( const MyContext * ctx,
OptWithPos & opt,
expr & output )
inlinestatic
1231 {
1232 if (ctx->skipping())
1233 return;
1234
1235 assert(opt.opt->is_vector());
1236 const ConfigOptionVectorBase* vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
1237 if (vec->empty())
1238 ctx->throw_exception(L("Indexing an empty vector variable"), opt.it_range);
1239
1240 // Helper to resolve a FloatOrPercent value (handles ratio_over chain for percent values).
1241 // elem_index: the element index used to access this vector element, so that
1242 // parent vectors (via ratio_over) use the same index rather than the current extruder.
1243 auto resolve_float_or_percent = [ctx, &opt, &output](const FloatOrPercent &fop, size_t elem_index) {
1244 std::string opt_key(opt.it_range.begin(), opt.it_range.end());
1245 if (boost::ends_with(opt_key, "line_width")) {
1246 // Line width supports defaults and a complex graph of dependencies.
1247 output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast<unsigned int>(ctx->current_extruder_id)));
1248 } else if (! fop.percent) {
1249 // Not a percent, just return the value.
1250 output.set_d(fop.value);
1251 } else {
1252 // Resolve dependencies using the "ratio_over" link to a parent value.
1253 const ConfigOptionDef *opt_def = print_config_def.get(opt_key);
1254 assert(opt_def != nullptr);
1255 double v = fop.value * 0.01; // percent to ratio
1256 for (;;) {
1257 const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over);
1258 if (opt_parent == nullptr)
1259 ctx->throw_exception(L("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies"), opt.it_range);
1260 if (boost::ends_with(opt_def->ratio_over, "line_width")) {
1261 // Line width supports defaults and a complex graph of dependencies.
1262 assert(opt_parent->type() == coFloatOrPercent);
1263 v *= Flow::extrusion_width(opt_def->ratio_over, static_cast<const ConfigOptionFloatOrPercent*>(opt_parent), *ctx, static_cast<unsigned int>(ctx->current_extruder_id));
1264 break;
1265 }
1266 if (opt_parent->type() == coFloat || opt_parent->type() == coFloatOrPercent) {
1267 v *= opt_parent->getFloat();
1268 if (opt_parent->type() == coFloat || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_parent)->percent)
1269 break;
1270 v *= 0.01; // percent to ratio
1271 } else if (opt_parent->type() == coFloats) {
1272 // Vector parent: extract the value for the current extruder.
1273 const ConfigOptionFloatsNullable *parent_nullable = dynamic_cast<const ConfigOptionFloatsNullable *>(opt_parent);
1274 if (parent_nullable) {
1275 v *= (parent_nullable->size() == 1) ? parent_nullable->get_at(0) : parent_nullable->get_at(elem_index);
1276 } else {
1277 const ConfigOptionFloats *parent_vec = static_cast<const ConfigOptionFloats *>(opt_parent);
1278 v *= (parent_vec->size() == 1) ? parent_vec->get_at(0) : parent_vec->get_at(elem_index);
1279 }
1280 break;
1281 } else if (opt_parent->type() == coFloatsOrPercents) {
1282 // Vector parent with percent support: extract the FloatOrPercent for the current extruder.
1283 const ConfigOptionFloatsOrPercentsNullable *parent_nullable = dynamic_cast<const ConfigOptionFloatsOrPercentsNullable *>(opt_parent);
1284 if (parent_nullable) {
1285 const FloatOrPercent &parent_fop = (parent_nullable->size() == 1) ? parent_nullable->get_at(0) : parent_nullable->get_at(elem_index);
1286 if (! parent_fop.percent) {
1287 v *= parent_fop.value;
1288 break;
1289 }
1290 v *= parent_fop.value * 0.01; // percent to ratio
1291 } else {
1292 const ConfigOptionFloatsOrPercents *parent_vec = static_cast<const ConfigOptionFloatsOrPercents *>(opt_parent);
1293 const FloatOrPercent &parent_fop = (parent_vec->size() == 1) ? parent_vec->get_at(0) : parent_vec->get_at(elem_index);
1294 if (! parent_fop.percent) {
1295 v *= parent_fop.value;
1296 break;
1297 }
1298 v *= parent_fop.value * 0.01; // percent to ratio
1299 }
1300 }
1301 // Continue one level up in the "ratio_over" hierarchy.
1302 opt_def = print_config_def.get(opt_def->ratio_over);
1303 assert(opt_def != nullptr);
1304 }
1305 output.set_d(v);
1306 }
1307 };
1308
1309 if (!opt.has_index()) {
1310 // Allow omitting extruder id when referencing vectors
1311 switch (opt.opt->type()) {
1312 case coFloats: {
1313 const ConfigOptionFloatsNullable* opt_floatsnullable = dynamic_cast<const ConfigOptionFloatsNullable *>(opt.opt);
1314 if (opt_floatsnullable) {
1315 if (opt_floatsnullable->size() == 1) { // old version
1316 output.set_d(opt_floatsnullable->get_at(0));
1317 } else {
1318 output.set_d(opt_floatsnullable->get_at(ctx->get_extruder_id()));
1319 }
1320 } else {
1321 const ConfigOptionFloats* opt_floats = static_cast<const ConfigOptionFloats*>(opt.opt);
1322 if (opt_floats->size() == 1) { // old version
1323 output.set_d(opt_floats->get_at(0));
1324 } else {
1325 output.set_d(opt_floats->get_at(ctx->get_extruder_id()));
1326 }
1327 }
1328 break;
1329 }
1330 case coFloatsOrPercents: {
1331 const ConfigOptionFloatsOrPercentsNullable *opt_vec_nullable = dynamic_cast<const ConfigOptionFloatsOrPercentsNullable *>(opt.opt);
1332 if (opt_vec_nullable) {
1333 size_t elem_index = (opt_vec_nullable->size() == 1) ? 0 : ctx->get_extruder_id();
1334 resolve_float_or_percent(opt_vec_nullable->get_at(elem_index), elem_index);
1335 } else {
1336 const ConfigOptionFloatsOrPercents *opt_vec = static_cast<const ConfigOptionFloatsOrPercents *>(opt.opt);
1337 size_t elem_index = (opt_vec->size() == 1) ? 0 : ctx->get_extruder_id();
1338 resolve_float_or_percent(opt_vec->get_at(elem_index), elem_index);
1339 }
1340 break;
1341 }
1342 default: ctx->throw_exception(L("Referencing a vector variable when scalar is expected"), opt.it_range);
1343 }
1344 } else {
1345 size_t idx = (opt.index < 0) ? 0 : (opt.index >= int(vec->size())) ? 0 : size_t(opt.index);
1346 if (vec->is_nil(idx))
1347 ctx->throw_exception(L("Trying to reference an undefined (nil) element of vector of optional values"), opt.it_range);
1348 switch (opt.opt->type()) {
1349 case coFloats: output.set_d(static_cast<const ConfigOptionFloats*>(opt.opt)->values[idx]); break;
1350 case coInts: output.set_i(static_cast<const ConfigOptionInts*>(opt.opt)->values[idx]); break;
1351 case coStrings: output.set_s(static_cast<const ConfigOptionStrings*>(opt.opt)->values[idx]); break;
1352 case coPercents: output.set_d(static_cast<const ConfigOptionPercents*>(opt.opt)->values[idx]); break;
1353 case coPoints: output.set_s(to_string(static_cast<const ConfigOptionPoints*>(opt.opt)->values[idx])); break;
1354 case coBools: output.set_b(static_cast<const ConfigOptionBools*>(opt.opt)->values[idx] != 0); break;
1355 case coEnums: output.set_i(static_cast<const ConfigOptionInts *>(opt.opt)->values[idx]); break;
1356 case coFloatsOrPercents: {
1357 const ConfigOptionFloatsOrPercentsNullable *opt_vec_nullable = dynamic_cast<const ConfigOptionFloatsOrPercentsNullable *>(opt.opt);
1358 if (opt_vec_nullable) {
1359 resolve_float_or_percent(opt_vec_nullable->values[idx], idx);
1360 } else {
1361 resolve_float_or_percent(static_cast<const ConfigOptionFloatsOrPercents *>(opt.opt)->values[idx], idx);
1362 }
1363 break;
1364 }
1365 default:
1366 ctx->throw_exception(L("Unsupported vector variable type"), opt.it_range);
1367 }
1368 }
1369 }
const double & get_at(size_t i) const
Definition Config.hpp:676
ConfigOptionFloatsTempl< true > ConfigOptionFloatsNullable
Definition Config.hpp:1016
ConfigOptionFloatsOrPercentsTempl< true > ConfigOptionFloatsOrPercentsNullable
Definition Config.hpp:1532
@ coFloatsOrPercents
Definition Config.hpp:202
ConfigOptionFloatsOrPercentsTempl< false > ConfigOptionFloatsOrPercents
Definition Config.hpp:1531
ConfigOptionFloatsTempl< false > ConfigOptionFloats
Definition Config.hpp:1015
double value
Definition Config.hpp:49

References Slic3r::coBools, Slic3r::coEnums, Slic3r::coFloat, Slic3r::coFloatOrPercent, Slic3r::coFloats, Slic3r::coFloatsOrPercents, Slic3r::coInts, Slic3r::coPercents, Slic3r::coPoints, Slic3r::coStrings, current_extruder_id, Slic3r::ConfigOptionVectorBase::empty(), Slic3r::Flow::extrusion_width(), Slic3r::ConfigOptionVector< double >::get_at(), Slic3r::ConfigOptionVector< FloatOrPercent >::get_at(), get_extruder_id(), Slic3r::ConfigOption::getFloat(), Slic3r::ConfigOptionVectorBase::is_nil(), L, Slic3r::ConfigOptionFloatOrPercent::percent, Slic3r::FloatOrPercent::percent, Slic3r::print_config_def, Slic3r::ConfigOptionDef::ratio_over, resolve_symbol(), Slic3r::client::expr::set_b(), Slic3r::client::expr::set_d(), Slic3r::client::expr::set_i(), Slic3r::client::expr::set_s(), Slic3r::ConfigOptionVector< double >::size(), Slic3r::ConfigOptionVector< FloatOrPercent >::size(), Slic3r::ConfigOptionVectorBase::size(), skipping(), throw_exception(), Slic3r::to_string(), Slic3r::ConfigOption::type(), Slic3r::FloatOrPercent::value, Slic3r::ConfigOptionVector< T >::values, and Slic3r::ConfigOptionVector< FloatOrPercent >::values.

Referenced by variable_value().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_size()

void Slic3r::client::MyContext::vector_size ( const MyContext * ctx,
OptWithPos & opt,
expr & out )
inlinestatic
1834 {
1835 if (! ctx->skipping()) {
1836 if (opt.has_index() || ! opt.opt->is_vector())
1837 ctx->throw_exception(L("parameter of size() is not a vector variable"), opt.it_range);
1838 out.set_i(int(static_cast<const ConfigOptionVectorBase*>(opt.opt)->size()));
1839 }
1840 out.it_range = opt.it_range;
1841 }

References Slic3r::client::expr::it_range, L, Slic3r::client::expr::set_i(), Slic3r::ConfigOptionVectorBase::size(), skipping(), and throw_exception().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_variable_assign_array()

void Slic3r::client::MyContext::vector_variable_assign_array ( const MyContext * ctx,
OptWithPos & lhs,
const expr & rhs_count,
const expr & rhs_value )
inlinestatic
1628 {
1629 if (! ctx->skipping()) {
1630 check_writable(ctx, lhs);
1631 if (lhs.opt->is_scalar())
1632 ctx->throw_exception(L("Cannot assign a vector value to a scalar variable."), rhs_value.it_range);
1633 vector_variable_assign_expr_with_count(ctx, lhs, rhs_count, rhs_value);
1634 }
1635 }
static void vector_variable_assign_expr_with_count(const MyContext *ctx, OptWithPos &lhs, const expr &rhs_count, const expr &rhs_value)
Definition PlaceholderParser.cpp:1460

References check_writable(), Slic3r::ConfigOption::is_scalar(), Slic3r::client::expr::it_range, L, Slic3r::client::OptWithPos::opt, skipping(), throw_exception(), and vector_variable_assign_expr_with_count().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_variable_assign_expr_with_count()

void Slic3r::client::MyContext::vector_variable_assign_expr_with_count ( const MyContext * ctx,
OptWithPos & lhs,
const expr & rhs_count,
const expr & rhs_value )
inlinestatic
1461 {
1462 assert(! ctx->skipping());
1463 size_t count = evaluate_count(rhs_count);
1464 auto *opt = const_cast<ConfigOption*>(lhs.opt);
1465 switch (lhs.opt->type()) {
1466 case coFloats:
1467 check_numeric(rhs_value);
1468 static_cast<ConfigOptionFloats*>(opt)->values.assign(count, rhs_value.as_d());
1469 break;
1470 case coInts:
1471 check_numeric(rhs_value);
1472 static_cast<ConfigOptionInts*>(opt)->values.assign(count, rhs_value.as_i());
1473 break;
1474 case coStrings:
1475 static_cast<ConfigOptionStrings*>(opt)->values.assign(count, rhs_value.to_string());
1476 break;
1477 case coBools:
1478 if (rhs_value.type() != expr::TYPE_BOOL)
1479 rhs_value.throw_exception(L("Right side is not a boolean expression"));
1480 static_cast<ConfigOptionBools*>(opt)->values.assign(count, rhs_value.b());
1481 break;
1482 default: assert(false);
1483 }
1484 }
ConfigOptionBoolsTempl< false > ConfigOptionBools
Definition Config.hpp:2066
static size_t evaluate_count(const expr &expr_count)
Definition PlaceholderParser.cpp:1381

References Slic3r::client::expr::as_d(), Slic3r::client::expr::as_i(), Slic3r::client::expr::b(), check_numeric(), Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coStrings, count, evaluate_count(), L, Slic3r::client::OptWithPos::opt, skipping(), Slic3r::client::expr::throw_exception(), Slic3r::client::expr::to_string(), Slic3r::client::expr::type(), Slic3r::ConfigOption::type(), and Slic3r::client::expr::TYPE_BOOL.

Referenced by vector_variable_assign_array(), and vector_variable_new_from_array().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_variable_assign_initializer_list()

void Slic3r::client::MyContext::vector_variable_assign_initializer_list ( const MyContext * ctx,
OptWithPos & lhs,
const std::vector< expr > & il )
inlinestatic
1647 {
1648 if (ctx->skipping())
1649 return;
1650
1651 check_writable(ctx, lhs);
1652
1653 if (lhs.opt->is_scalar()) {
1654 if (il.size() == 1)
1655 // scalar_var = ( scalar )
1656 scalar_variable_assign_scalar_expression(ctx, lhs, il.front());
1657 else
1658 // scalar_var = ()
1659 // or
1660 // scalar_var = ( scalar, scalar, ... )
1661 ctx->throw_exception(L("Cannot assign a vector value to a scalar variable."), lhs.it_range);
1662 }
1663
1664 auto check_numeric_vector = [](const std::vector<expr> &il) {
1665 for (auto &i : il)
1666 if (! i.numeric_type())
1667 i.throw_exception(L("Right side is not a numeric expression"));
1668 };
1669
1670 ConfigOption *opt = const_cast<ConfigOption*>(lhs.opt);
1671 switch (lhs.opt->type()) {
1672 case coFloats:
1673 check_numeric_vector(il);
1674 fill_vector_from_initializer_list<ConfigOptionFloats>(opt, il, [](auto &v){ return v.as_d(); });
1675 break;
1676 case coInts:
1677 check_numeric_vector(il);
1678 fill_vector_from_initializer_list<ConfigOptionInts>(opt, il, [](auto &v){ return v.as_i(); });
1679 break;
1680 case coStrings:
1681 fill_vector_from_initializer_list<ConfigOptionStrings>(opt, il, [](auto &v){ return v.to_string(); });
1682 break;
1683 case coBools:
1684 for (auto &i : il)
1685 if (i.type() != expr::TYPE_BOOL)
1686 i.throw_exception(L("Right side is not a boolean expression"));
1687 fill_vector_from_initializer_list<ConfigOptionBools>(opt, il, [](auto &v){ return v.b(); });
1688 break;
1689 default: assert(false);
1690 }
1691 }
static void scalar_variable_assign_scalar_expression(const MyContext *ctx, OptWithPos &opt, const expr &param)
Definition PlaceholderParser.cpp:1560
static void fill_vector_from_initializer_list(ConfigOption *opt, const std::vector< expr > &il, RightValueEvaluate rv_eval)
Definition PlaceholderParser.cpp:1638

References check_writable(), Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coStrings, fill_vector_from_initializer_list(), Slic3r::ConfigOption::is_scalar(), Slic3r::client::OptWithPos::it_range, L, Slic3r::client::OptWithPos::opt, scalar_variable_assign_scalar_expression(), skipping(), throw_exception(), Slic3r::ConfigOption::type(), and Slic3r::client::expr::TYPE_BOOL.

Referenced by Slic3r::client::macro_processor::macro_processor(), and vector_variable_new_from_initializer_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_variable_element_assign_scalar()

void Slic3r::client::MyContext::vector_variable_element_assign_scalar ( const MyContext * ctx,
OptWithPos & lhs,
const expr & rhs )
inlinestatic
1423 {
1424 assert(! ctx->skipping());
1425 assert(lhs.opt->is_vector());
1426 check_writable(ctx, lhs);
1427 if (! lhs.has_index())
1428 ctx->throw_exception(L("Referencing an output vector variable when scalar is expected"), lhs.it_range);
1429 ConfigOptionVectorBase *vec = const_cast<ConfigOptionVectorBase*>(static_cast<const ConfigOptionVectorBase*>(lhs.opt));
1430 if (vec->empty())
1431 ctx->throw_exception(L("Indexing an empty vector variable"), lhs.it_range);
1432 if (lhs.index >= int(vec->size()))
1433 ctx->throw_exception(L("Index out of range"), lhs.it_range);
1434 switch (lhs.opt->type()) {
1435 case coFloats:
1436 check_numeric(rhs);
1437 static_cast<ConfigOptionFloats*>(vec)->values[lhs.index] = rhs.as_d();
1438 break;
1439 case coInts:
1440 check_numeric(rhs);
1441 static_cast<ConfigOptionInts*>(vec)->values[lhs.index] = rhs.as_i();
1442 break;
1443 case coStrings:
1444 static_cast<ConfigOptionStrings*>(vec)->values[lhs.index] = rhs.to_string();
1445 break;
1446 case coPercents:
1447 check_numeric(rhs);
1448 static_cast<ConfigOptionPercents*>(vec)->values[lhs.index] = rhs.as_d();
1449 break;
1450 case coBools:
1451 if (rhs.type() != expr::TYPE_BOOL)
1452 ctx->throw_exception(L("Right side is not a boolean expression"), rhs.it_range);
1453 static_cast<ConfigOptionBools*>(vec)->values[lhs.index] = rhs.b();
1454 break;
1455 default:
1456 ctx->throw_exception(L("Unsupported output vector variable type"), lhs.it_range);
1457 }
1458 }
ConfigOptionPercentsTempl< false > ConfigOptionPercents
Definition Config.hpp:1334
@ coPercents
Definition Config.hpp:198

References Slic3r::client::expr::as_d(), Slic3r::client::expr::as_i(), Slic3r::client::expr::b(), check_numeric(), check_writable(), Slic3r::coBools, Slic3r::coFloats, Slic3r::coInts, Slic3r::coPercents, Slic3r::coStrings, Slic3r::ConfigOptionVectorBase::empty(), Slic3r::client::OptWithPos::has_index(), Slic3r::client::OptWithPos::index, Slic3r::ConfigOption::is_vector(), Slic3r::client::expr::it_range, Slic3r::client::OptWithPos::it_range, L, Slic3r::client::OptWithPos::opt, Slic3r::ConfigOptionVectorBase::size(), skipping(), throw_exception(), Slic3r::client::expr::to_string(), Slic3r::client::expr::type(), Slic3r::ConfigOption::type(), and Slic3r::client::expr::TYPE_BOOL.

Referenced by scalar_variable_assign_scalar_expression().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_variable_new_from_array()

void Slic3r::client::MyContext::vector_variable_new_from_array ( const MyContext * ctx,
bool global_variable,
NewOldVariable & lhs,
const expr & rhs_count,
const expr & rhs_value )
inlinestatic
1602 {
1603 if (ctx->skipping()) {
1604 } else if (lhs.opt) {
1605 if (lhs.opt->is_scalar())
1606 ctx->throw_exception(L("Cannot assign a vector value to a scalar variable."), rhs_value.it_range);
1607 OptWithPos lhs_opt{ lhs.opt, lhs.it_range, true };
1608 vector_variable_assign_expr_with_count(ctx, lhs_opt, rhs_count, rhs_value);
1609 } else {
1610 size_t count = evaluate_count(rhs_count);
1611 std::unique_ptr<ConfigOption> opt_new;
1612 switch (rhs_value.type()) {
1613 case expr::TYPE_BOOL: opt_new = std::make_unique<ConfigOptionBools>(count, rhs_value.b()); break;
1614 case expr::TYPE_INT: opt_new = std::make_unique<ConfigOptionInts>(count, rhs_value.i()); break;
1615 case expr::TYPE_DOUBLE: opt_new = std::make_unique<ConfigOptionFloats>(count, rhs_value.d()); break;
1616 case expr::TYPE_STRING: opt_new = std::make_unique<ConfigOptionStrings>(count, rhs_value.s()); break;
1617 default: assert(false);
1618 }
1619 const_cast<MyContext*>(ctx)->store_new_variable(lhs.name, std::move(opt_new), global_variable);
1620 }
1621 }

References Slic3r::client::expr::b(), count, Slic3r::client::expr::d(), evaluate_count(), Slic3r::client::expr::i(), Slic3r::ConfigOption::is_scalar(), Slic3r::client::expr::it_range, Slic3r::client::MyContext::NewOldVariable::it_range, L, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::client::MyContext::NewOldVariable::opt, Slic3r::client::expr::s(), skipping(), store_new_variable(), throw_exception(), Slic3r::client::expr::type(), Slic3r::client::expr::TYPE_BOOL, Slic3r::client::expr::TYPE_DOUBLE, Slic3r::client::expr::TYPE_INT, Slic3r::client::expr::TYPE_STRING, and vector_variable_assign_expr_with_count().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_variable_new_from_copy()

bool Slic3r::client::MyContext::vector_variable_new_from_copy ( const MyContext * ctx,
bool global_variable,
NewOldVariable & lhs,
const OptWithPos & rhs )
inlinestatic
1787 {
1788 if (ctx->skipping())
1789 // Skipping, let conditional_expression parse the whole right hand side, which may continue after the variable reference.
1790 return false;
1791
1792 if (lhs.opt) {
1793 assert(lhs.opt->is_vector());
1794 OptWithPos lhs_opt{ lhs.opt, lhs.it_range, true };
1795 copy_vector_variable_to_vector_variable(ctx, lhs_opt, rhs);
1796 } else {
1797 if (rhs.has_index() || ! rhs.opt->is_vector())
1798 // Stop parsing, let the other rules resolve this case.
1799 return false;
1800 if (rhs.opt->is_nil())
1801 ctx->throw_exception(L("Some elements of the right hand side vector variable of optional values are undefined (nil)"), rhs.it_range);
1802 // Clone the vector variable.
1803 std::unique_ptr<ConfigOption> opt_new;
1804 if (one_of(rhs.opt->type(), { coFloats, coInts, coStrings, coBools }))
1805 opt_new = std::unique_ptr<ConfigOption>(rhs.opt->clone());
1806 else if (rhs.opt->type() == coPercents)
1807 opt_new = std::make_unique<ConfigOptionFloats>(static_cast<const ConfigOptionPercents*>(rhs.opt)->values);
1808 else
1809 ctx->throw_exception(L("Duplicating this type of vector variable is not supported"), rhs.it_range);
1810 const_cast<MyContext*>(ctx)->store_new_variable(lhs.name, std::move(opt_new), global_variable);
1811 }
1812 // Continue parsing.
1813 return true;
1814 }
std::vector< double > values
Definition Config.hpp:418
bool one_of(const ValueType &v, const ContainerType &c)
Definition libslic3r.h:295
static void copy_vector_variable_to_vector_variable(const MyContext *ctx, OptWithPos &lhs, const OptWithPos &rhs)
Definition PlaceholderParser.cpp:1753

References Slic3r::ConfigOption::clone(), Slic3r::coPercents, copy_vector_variable_to_vector_variable(), Slic3r::client::OptWithPos::has_index(), Slic3r::ConfigOption::is_nil(), Slic3r::ConfigOption::is_vector(), Slic3r::client::MyContext::NewOldVariable::it_range, Slic3r::client::OptWithPos::it_range, L, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::one_of(), Slic3r::client::MyContext::NewOldVariable::opt, Slic3r::client::OptWithPos::opt, skipping(), store_new_variable(), throw_exception(), and Slic3r::ConfigOption::type().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_variable_new_from_initializer_list()

void Slic3r::client::MyContext::vector_variable_new_from_initializer_list ( const MyContext * ctx,
bool global_variable,
NewOldVariable & lhs,
const std::vector< expr > & il )
inlinestatic
1698 {
1699 if (ctx->skipping())
1700 return;
1701
1702 if (lhs.opt) {
1703 // Assign to an existing vector variable.
1704 OptWithPos lhs_opt{ lhs.opt, lhs.it_range, true };
1706 } else {
1707 if (il.empty())
1708 ctx->throw_exception(L("Cannot create vector variable from an empty initializer list, because its type cannot be deduced."), lhs.it_range);
1709 // Allocate a new vector variable.
1710 // First guesstimate type of the output vector.
1711 size_t num_bool = 0;
1712 size_t num_int = 0;
1713 size_t num_double = 0;
1714 size_t num_string = 0;
1715 for (auto &i : il)
1716 switch (i.type()) {
1717 case expr::TYPE_BOOL: ++ num_bool; break;
1718 case expr::TYPE_INT: ++ num_int; break;
1719 case expr::TYPE_DOUBLE: ++ num_double; break;
1720 case expr::TYPE_STRING: ++ num_string; break;
1721 default: assert(false);
1722 }
1723 std::unique_ptr<ConfigOption> opt_new;
1724 if (num_string > 0)
1725 // Convert everything to strings.
1726 opt_new = std::make_unique<ConfigOptionStrings>();
1727 else if (num_bool > 0) {
1728 if (num_double + num_int > 0)
1729 ctx->throw_exception(L("Right side is not valid: Mixing numeric and boolean types."), IteratorRange{ il.front().it_range.begin(), il.back().it_range.end() });
1730 opt_new = std::make_unique<ConfigOptionBools>();
1731 } else {
1732 // Output is numeric.
1733 if (num_double == 0)
1734 opt_new = std::make_unique<ConfigOptionInts>();
1735 else
1736 opt_new = std::make_unique<ConfigOptionFloats>();
1737 }
1738 OptWithPos lhs_opt{ opt_new.get(), lhs.it_range, true };
1740 const_cast<MyContext*>(ctx)->store_new_variable(lhs.name, std::move(opt_new), global_variable);
1741 }
1742 }
static void vector_variable_assign_initializer_list(const MyContext *ctx, OptWithPos &lhs, const std::vector< expr > &il)
Definition PlaceholderParser.cpp:1646

References Slic3r::client::MyContext::NewOldVariable::it_range, L, Slic3r::client::MyContext::NewOldVariable::name, Slic3r::client::MyContext::NewOldVariable::opt, skipping(), store_new_variable(), throw_exception(), Slic3r::client::expr::TYPE_BOOL, Slic3r::client::expr::TYPE_DOUBLE, Slic3r::client::expr::TYPE_INT, Slic3r::client::expr::TYPE_STRING, and vector_variable_assign_initializer_list().

Referenced by Slic3r::client::macro_processor::macro_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ config

◆ config_local

DynamicConfig Slic3r::client::MyContext::config_local
mutable

Referenced by new_old_variable().

◆ config_outputs

DynamicConfig* Slic3r::client::MyContext::config_outputs = nullptr
mutable

◆ config_override

◆ context_data

◆ current_extruder_id

◆ deferred_tags

const std::set<std::string>* Slic3r::client::MyContext::deferred_tags = nullptr

◆ error_message

std::string Slic3r::client::MyContext::error_message

◆ external_config

const DynamicConfig* Slic3r::client::MyContext::external_config = nullptr

◆ inactive_local_variables

std::set<std::string> Slic3r::client::MyContext::inactive_local_variables
mutable

◆ just_boolean_expression

bool Slic3r::client::MyContext::just_boolean_expression = false

◆ m_depth_suppressed

int Slic3r::client::MyContext::m_depth_suppressed { 0 }
mutableprivate
1939{ 0 };

Referenced by block_enter(), block_exit(), block_exit_ternary(), and skipping().

◆ tag_to_error_message

std::map< std::string, std::string > Slic3r::client::MyContext::tag_to_error_message
static
Initial value:
= {
{ "eoi", L("Unknown syntax error") },
{ "start", L("Unknown syntax error") },
{ "text", L("Invalid text.") },
{ "text_block", L("Invalid text block.") },
{ "macro", L("Invalid macro.") },
{ "repeat", L("Unknown syntax error") },
{ "if_else_output", L("Not an {if}{else}{endif} macro.") },
{ "switch_output", L("Not a {switch} macro.") },
{ "legacy_variable_expansion", L("Expecting a legacy variable expansion format") },
{ "identifier", L("Expecting an identifier.") },
{ "conditional_expression", L("Expecting a conditional expression.") },
{ "logical_or_expression", L("Expecting a boolean expression.") },
{ "logical_and_expression", L("Expecting a boolean expression.") },
{ "equality_expression", L("Expecting an expression.") },
{ "bool_expr_eval", L("Expecting a boolean expression.")},
{ "relational_expression", L("Expecting an expression.") },
{ "additive_expression", L("Expecting an expression.") },
{ "multiplicative_expression", L("Expecting an expression.") },
{ "unary_expression", L("Expecting an expression.") },
{ "optional_parameter", L("Expecting a closing brace or an optional parameter.") },
{ "one_of_list", L("Expecting a list of string patterns (simple text or regexp)") },
{ "variable_reference", L("Expecting a variable reference.")},
{ "variable", L("Expecting a variable name.")},
{ "regular_expression", L("Expecting a regular expression.")}
}

Referenced by process_error_message().


The documentation for this struct was generated from the following file: