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..64735a1 100644 --- a/include/cura-formulae-engine/ast/ast.h +++ b/include/cura-formulae-engine/ast/ast.h @@ -1,12 +1,12 @@ #pragma once -#include "cura-formulae-engine/eval.h" - -#include - #include #include +#include #include +#include + +#include "cura-formulae-engine/eval.h" namespace CuraFormulaeEngine::eval { @@ -36,10 +36,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 +55,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 +153,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..9b775e2 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