From 614084257be81c9b357d8c02349a3e4f356eb29e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 31 Mar 2026 22:17:47 +0200 Subject: [PATCH 1/3] Add a Reusable ChainableEnvironment and optimize the EnvironmentMap CURA-13049 --- conandata.yml | 2 +- include/cura-formulae-engine/ast/ast.h | 66 ++++++++++++++++++------- src/ast/ast.cpp | 68 +++++++++++++++++--------- 3 files changed, 95 insertions(+), 41 deletions(-) diff --git a/conandata.yml b/conandata.yml index 708b253..d6a1e88 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1 +1 @@ -version: "1.0.0" \ No newline at end of file +version: "1.1.0" diff --git a/include/cura-formulae-engine/ast/ast.h b/include/cura-formulae-engine/ast/ast.h index 47ab271..8d6ddec 100644 --- a/include/cura-formulae-engine/ast/ast.h +++ b/include/cura-formulae-engine/ast/ast.h @@ -1,12 +1,11 @@ #pragma once -#include "cura-formulae-engine/eval.h" - -#include - #include #include #include +#include + +#include "cura-formulae-engine/eval.h" namespace CuraFormulaeEngine::eval { @@ -36,10 +35,13 @@ class EnvironmentMap : public Environment { private: std::unordered_map environment_ = {}; -public: +public: EnvironmentMap() = default; - explicit EnvironmentMap(const std::unordered_map& map) : environment_(map) {} + explicit EnvironmentMap(const std::unordered_map& map) + : environment_(map) + { + } ~EnvironmentMap() override = default; [[nodiscard]] std::optional get(const std::string& key) const noexcept override; @@ -52,31 +54,58 @@ class EnvironmentMap : public Environment void set(const std::string& key, const eval::Value& value) noexcept; - [[nodiscard]] EnvironmentMap clone() const noexcept; + void add(const std::unordered_map values); + [[nodiscard]] EnvironmentMap clone() const noexcept; }; -class LocalEnvironment : public Environment +class ChainableEnvironment : public Environment { +private: + const Environment* shadow_environment_{ nullptr }; + public: + explicit ChainableEnvironment(const Environment* shadow_environment = nullptr) + : shadow_environment_(shadow_environment) + { + } + ~ChainableEnvironment() override = default; - LocalEnvironment() = default; - explicit LocalEnvironment(const Environment* shadow_environment_) - : shadow_environment_(shadow_environment_) + [[nodiscard]] std::optional get(const std::string& key) const noexcept override final; + + [[nodiscard]] bool has(const std::string& key) const noexcept override final; + + [[nodiscard]] std::unordered_map getAll() const noexcept override final; + +protected: + [[nodiscard]] virtual std::optional getImpl(const std::string& key) const noexcept = 0; + + [[nodiscard]] virtual bool hasImpl(const std::string& key) const noexcept = 0; + + [[nodiscard]] virtual std::unordered_map getAllImpl() const noexcept = 0; +}; + +class LocalEnvironment : public ChainableEnvironment +{ +private: + EnvironmentMap local_environment_; + +public: + explicit LocalEnvironment(const Environment* shadow_environment = nullptr) + : ChainableEnvironment(shadow_environment) { } ~LocalEnvironment() override = default; - EnvironmentMap local_environment_ = {}; - const Environment* shadow_environment_; - - [[nodiscard]] std::optional get(const std::string& key) const noexcept override; + [[nodiscard]] std::optional getImpl(const std::string& key) const noexcept override; - [[nodiscard]] bool has(const std::string& key) const noexcept override; + [[nodiscard]] bool hasImpl(const std::string& key) const noexcept override; - [[nodiscard]] std::unordered_map getAll() const noexcept override; + [[nodiscard]] std::unordered_map getAllImpl() const noexcept override; void set(const std::string& key, const eval::Value& value); + + void add(const std::unordered_map values); }; } // namespace CuraFormulaeEngine::env @@ -123,7 +152,8 @@ struct Expr [[nodiscard]] virtual bool deepEq(const Expr& other) const = 0; /** - * @brief Traverses the expression tree and applies the visitor function to each node. + * @brief Traverses the expression tree and applies the visitor function to + * each node. * * @param visitor The visitor function to apply to each node. */ diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 9d1b1bc..aa39def 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -5,11 +5,12 @@ namespace CuraFormulaeEngine::env std::optional EnvironmentMap::get(const std::string& key) const noexcept { - if (!has(key)) + auto iterator = environment_.find(key); + if (iterator == environment_.end()) { return std::nullopt; } - return environment_.at(key); + return iterator->second; } bool EnvironmentMap::has(const std::string& key) const noexcept @@ -32,44 +33,67 @@ void EnvironmentMap::set(const std::string& key, const eval::Value& value) noexc environment_.insert_or_assign(key, value); } +void EnvironmentMap::add(const std::unordered_map values) +{ + environment_.insert(values.begin(), values.end()); +} + EnvironmentMap EnvironmentMap::clone() const noexcept { - return EnvironmentMap{environment_}; + return EnvironmentMap{ environment_ }; } -std::optional LocalEnvironment::get(const std::string& key) const noexcept +std::optional LocalEnvironment::getImpl(const std::string& key) const noexcept { - if (local_environment_.has(key)) - { - return local_environment_.get(key); - } - if (shadow_environment_ && shadow_environment_->has(key)) + return local_environment_.get(key); +} + +bool LocalEnvironment::hasImpl(const std::string& key) const noexcept +{ + return local_environment_.has(key); +} + +std::unordered_map LocalEnvironment::getAllImpl() const noexcept +{ + return local_environment_.getAll(); +} + +void LocalEnvironment::set(const std::string& key, const eval::Value& value) +{ + local_environment_.set(key, value); +} + +void LocalEnvironment::add(const std::unordered_map values) +{ + local_environment_.add(values); +} + +std::optional ChainableEnvironment::get(const std::string& key) const noexcept +{ + std::optional value = getImpl(key); + if (! value.has_value() && shadow_environment_) { - return shadow_environment_->get(key); + value = shadow_environment_->get(key); } - return std::nullopt; + return value; } -bool LocalEnvironment::has(const std::string& key) const noexcept +bool ChainableEnvironment::has(const std::string& key) const noexcept { - return local_environment_.has(key) || (shadow_environment_ && shadow_environment_->has(key)); + return hasImpl(key) || (shadow_environment_ && shadow_environment_->has(key)); } -std::unordered_map LocalEnvironment::getAll() const noexcept +std::unordered_map ChainableEnvironment::getAll() const noexcept { std::unordered_map all; - if (shadow_environment_) { + if (shadow_environment_) + { all = shadow_environment_->getAll(); } - auto scoped = local_environment_.getAll(); + auto scoped = getAllImpl(); all.insert(scoped.begin(), scoped.end()); return all; } -void LocalEnvironment::set(const std::string& key, const eval::Value& value) -{ - local_environment_.set(key, value); -} - -} // namespace CuraFormulaeEngine::env \ No newline at end of file +} // namespace CuraFormulaeEngine::env From a6bc21316d7b06212c1c3c659b67280d63937efd Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 28 Apr 2026 16:03:01 +0200 Subject: [PATCH 2/3] Add possibly missing header CURA-13049 --- include/cura-formulae-engine/ast/ast.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/cura-formulae-engine/ast/ast.h b/include/cura-formulae-engine/ast/ast.h index 8d6ddec..8f96ab5 100644 --- a/include/cura-formulae-engine/ast/ast.h +++ b/include/cura-formulae-engine/ast/ast.h @@ -2,6 +2,7 @@ #include #include +#include #include #include From 8f6f71f8c6b7b976e66b13e429587ef42c70ca4e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 28 Apr 2026 16:06:48 +0200 Subject: [PATCH 3/3] Pass maps by reference to avoid copy CURA-13049 --- include/cura-formulae-engine/ast/ast.h | 4 ++-- src/ast/ast.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/cura-formulae-engine/ast/ast.h b/include/cura-formulae-engine/ast/ast.h index 8f96ab5..64735a1 100644 --- a/include/cura-formulae-engine/ast/ast.h +++ b/include/cura-formulae-engine/ast/ast.h @@ -55,7 +55,7 @@ class EnvironmentMap : public Environment void set(const std::string& key, const eval::Value& value) noexcept; - void add(const std::unordered_map values); + void add(const std::unordered_map& values); [[nodiscard]] EnvironmentMap clone() const noexcept; }; @@ -106,7 +106,7 @@ class LocalEnvironment : public ChainableEnvironment void set(const std::string& key, const eval::Value& value); - void add(const std::unordered_map values); + void add(const std::unordered_map& values); }; } // namespace CuraFormulaeEngine::env diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index aa39def..9b775e2 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -33,7 +33,7 @@ void EnvironmentMap::set(const std::string& key, const eval::Value& value) noexc environment_.insert_or_assign(key, value); } -void EnvironmentMap::add(const std::unordered_map values) +void EnvironmentMap::add(const std::unordered_map& values) { environment_.insert(values.begin(), values.end()); } @@ -63,7 +63,7 @@ void LocalEnvironment::set(const std::string& key, const eval::Value& value) local_environment_.set(key, value); } -void LocalEnvironment::add(const std::unordered_map values) +void LocalEnvironment::add(const std::unordered_map& values) { local_environment_.add(values); }