#pragma once #include #include #include #include #include // for clangd #include "error_handling.hpp" #include "utils.hpp" namespace info { template class ContextManager { public: ContextManager() { contexts_.emplace_back(true); // no difference ?? } template utils::IdType AddValue(const T& value, utils::ValueType value_type) { return value_manager_.AddValue(value, value_type); } utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) { return value_manager_.AddAnyValue(std::move(value), value_type); } template std::optional GetValue(utils::IdType value_id) { return value_manager_.template GetValue(value_id); } Value* GetAnyValue(utils::IdType value_id) { return value_manager_.GetAnyValue(value_id); } bool AddValueRequirement(utils::IdType type, utils::IdType requrement) { return value_manager_.AddValueRequirement(type, requrement); } bool EqualValues(utils::IdType first_type, utils::IdType second_type) { return value_manager_.EqualValues(first_type, second_type); } utils::ValueType GetValueType(utils::IdType value_id) { return value_manager_.GetValueType(value_id); } utils::IdType ToModifiedValue(utils::IdType value_id, utils::ValueType new_value_type) { Value value = *GetAnyValue(value_id); return AddAnyValue(std::move(value), new_value_type); } ValueManager* GetValueManager() { return &value_manager_; } void EnterContext(bool is_hiding_previous = false) { contexts_.emplace_back(is_hiding_previous); } void ExitContext() { if (contexts_.empty()) { error_handling::HandleInternalError("contexts_ is empty", "ContextManager.ExitContext", std::nullopt); } contexts_.pop_back(); } void ChangeHidingOfCurrentContextTo(bool is_hiding_previous) { contexts_.back().ChangeHidingTo(is_hiding_previous); } bool DefineVariable(const std::string& name, utils::IdType value_id) { return contexts_.back().DefineVariable(name, value_id); } bool DefineLocalType(const std::string& name, utils::IdType type_id) { return contexts_.back().DefineLocalType(name, type_id); } bool AssignVariable(const std::string& name, utils::IdType value_id) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { if (contexts_[i].AssignVariable(name, value_id)) { return true; } if (contexts_[i].IsHidingPrevious()) { break; } } return false; } bool AssignLocalType(const std::string& name, utils::IdType type_id) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { if (contexts_[i].AssignLocalType(name, type_id)) { return true; } if (contexts_[i].IsHidingPrevious()) { break; } } return false; } bool RemoveVariable(const std::string& name) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { if (contexts_[i].RemoveVariable(name)) { return true; } if (contexts_[i].IsHidingPrevious()) { break; } } return false; } void EnterVariableContext(const std::string& name, utils::IdType value_id, bool is_hiding_previous = false) { EnterContext(is_hiding_previous); DefineVariable(name, value_id); } std::optional FindVariable(const std::string& name) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { auto maybe_variable = contexts_[i].FindVariable(name); if (maybe_variable.has_value()) { return maybe_variable.value(); } if (contexts_[i].IsHidingPrevious()) { break; } } return std::nullopt; } std::optional FindLocalType(const std::string& name) { for (ssize_t i = (ssize_t)contexts_.size() - 1; i >= 0; --i) { auto maybe_type = contexts_[i].FindLocalType(name); if (maybe_type.has_value()) { return maybe_type.value(); } if (contexts_[i].IsHidingPrevious()) { break; } } return std::nullopt; } private: class Context { public: explicit Context(bool is_hiding_previous) : is_hiding_previous_(is_hiding_previous) {} bool DefineVariable(const std::string& name, utils::IdType value_id) { if (name == "_") { // placeholder return true; } if (variables_.count(name) != 0) { return false; } variables_[name] = value_id; return true; } bool DefineLocalType(const std::string& name, utils::IdType type_id) { if (local_types_.count(name) != 0) { return false; } local_types_[name] = type_id; return true; } bool AssignVariable(const std::string& name, utils::IdType value_id) { if (name == "_") { // placeholder return true; } auto variable_iter = variables_.find(name); if (variable_iter == variables_.end()) { return false; } variable_iter->second = value_id; return true; } bool AssignLocalType(const std::string& name, utils::IdType type_id) { auto local_type_iter = local_types_.find(name); if (local_type_iter == local_types_.end()) { return false; } local_type_iter->second = type_id; return true; } bool RemoveVariable(const std::string& name) { return variables_.erase(name); } std::optional FindVariable(const std::string& name) { auto variable_iter = variables_.find(name); if (variable_iter == variables_.end()) { return std::nullopt; } return variable_iter->second; } std::optional FindLocalType(const std::string& name) { auto local_abstract_type_iter = local_types_.find(name); if (local_abstract_type_iter == local_types_.end()) { return std::nullopt; } return local_abstract_type_iter->second; } bool IsHidingPrevious() { return is_hiding_previous_; } void ChangeHidingTo(bool is_hiding_previous) { is_hiding_previous_ = is_hiding_previous; } private: std::unordered_map variables_; std::unordered_map local_types_; bool is_hiding_previous_ = false; }; std::vector contexts_; ValueManager value_manager_; }; } // namespace info