#pragma once #include #include #include #include // for clangd #include "interpreter_tree.hpp" #include "utils.hpp" namespace info::value { struct ValueManager; struct Unit {}; struct InternalValue { public: InternalValue() = default; template explicit InternalValue(const T& value) : value(value) {} // move ?? template std::optional GetValue() { if (!std::holds_alternative(value)) { return std::nullopt; } return &std::get(value); } std::optional GetFieldValue(const std::string& name); public: std::variant value; }; struct TupleValue { public: TupleValue() = default; TupleValue(std::vector, utils::IdType>>&& fields, ValueManager* value_manager) : fields(std::move(fields)), value_manager_(value_manager) {} std::optional GetFieldValue(const std::string& name); public: std::vector, utils::IdType>> fields; private: ValueManager* value_manager_ = nullptr; }; struct VariantValue { public: explicit VariantValue() = default; VariantValue(TupleValue&& value, size_t current_constructor) : value(std::move(value)), current_constructor(current_constructor) {} public: TupleValue value; size_t current_constructor; std::optional GetFieldValue(const std::string& name); }; struct ReferenceToValue { public: ReferenceToValue() = default; ReferenceToValue(const std::vector& references, utils::IdType value, ValueManager* value_manager) : references(references), value(value), value_manager_(value_manager) {} public: std::vector references; utils::IdType value; std::optional GetFieldValue(const std::string& name); private: ValueManager* value_manager_ = nullptr; }; struct FunctionValue { public: FunctionValue() = default; template FunctionValue(const T& function, ValueManager* value_manager) : function(function), value_manager_(value_manager) {} public: std::variant function; std::optional GetFieldValue(const std::string& name); private: ValueManager* value_manager_ = nullptr; }; struct ArrayValue { public: ArrayValue() = default; ArrayValue(std::vector&& elements, bool is_constant_size, ValueManager* value_manager) : elements(std::move(elements)), is_constant_size(is_constant_size), value_manager_(value_manager) {} public: std::vector elements; bool is_constant_size = false; std::optional GetFieldValue(const std::string& name); private: ValueManager* value_manager_ = nullptr; }; struct OptionalValue { public: OptionalValue() = default; OptionalValue(std::optional value, ValueManager* value_manager) : value(value), value_manager_(value_manager) {} std::optional GetFieldValue(const std::string& name); public: std::optional value; private: ValueManager* value_manager_ = nullptr; }; struct Value { // DefinedValue ?? public: Value() = default; template explicit Value(const T& value) : value(value) {} // move ?? std::optional GetFieldValue(const std::string& name); public: std::variant value; }; class ValueManager { public: template utils::IdType AddValue(const T& value, utils::ValueType value_type) { values_.push_back(std::pair {Value(value), value_type}); return values_.size() - 1; } utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) { values_.push_back(std::pair {std::move(value), value_type}); return values_.size() - 1; } template std::optional GetValue(utils::IdType value_id) { if (!std::holds_alternative(values_.at(value_id).first.value)) { return std::nullopt; } return &std::get(values_.at(value_id).first.value); } Value* GetAnyValue(utils::IdType value_id) { return &values_.at(value_id).first; } utils::ValueType GetValueType(utils::IdType value_id) { return values_.at(value_id).second; } bool EqualValues(utils::IdType first_value, utils::IdType second_value) = delete; // TODO bool AddValueRequirement(utils::IdType value, utils::IdType requrement) = delete; private: std::vector> values_; }; } // namespace info::value