#pragma once #include #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); } bool Same(const InternalValue& value) const; std::optional GetFieldValue(const std::string& name) const; utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); public: std::variant value; }; struct TupleValue { /// no need to store strings (only store associated type) ?? public: TupleValue() = default; TupleValue(std::vector, utils::IdType>>&& fields, ValueManager* value_manager) : fields(std::move(fields)), value_manager_(value_manager) {} bool Same(const TupleValue& other_value) const; std::optional GetFieldValue(const std::string& name) const; utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); // TODO 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) {} bool Same(const VariantValue& other_value) const; std::optional GetFieldValue(const std::string& name) const; utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); public: TupleValue value; size_t current_constructor; }; struct ReferenceToValue { public: ReferenceToValue() = default; ReferenceToValue(const std::vector& references, utils::IdType value, ValueManager* value_manager) : references(references), value(value), value_manager_(value_manager) {} bool Same(const ReferenceToValue& other_value) const; std::optional GetFieldValue(const std::string& name) const; utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); public: std::vector references; utils::IdType value; private: ValueManager* value_manager_ = nullptr; }; struct FunctionValue { public: FunctionValue() = default; template FunctionValue(const T& function, ValueManager* value_manager) : function(function), value_manager_(value_manager) {} bool Same(const FunctionValue& other_value) const; std::optional GetFieldValue(const std::string& name) const; utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); public: std::variant function; 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) {} bool Same(const ArrayValue& other_value) const; std::optional GetFieldValue(const std::string& name) const; utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); public: std::vector elements; bool is_constant_size = false; private: ValueManager* value_manager_ = nullptr; }; struct OptionalValue { public: OptionalValue() = default; OptionalValue(std::optional value, ValueManager* value_manager) : value(value), value_manager_(value_manager) {} bool Same(const OptionalValue& other_value) const; std::optional GetFieldValue(const std::string& name) const; utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); public: std::optional value; private: ValueManager* value_manager_ = nullptr; }; struct Value { // DefinedValue ?? public: Value() = default; template explicit Value(const T& value) : value(value) {} // move ?? bool Same(const Value& other_value) const; std::optional GetFieldValue(const std::string& name) const; utils::IdType DeepCopy(ValueManager* value_manager, utils::ValueType new_value_type); public: std::variant value; }; class ValueManager { public: template utils::IdType ExplicitAddValue(const T& value, utils::ValueType value_type) { values_.push_back(std::pair {Value(value), value_type}); return values_.size() - 1; } utils::IdType ExplicitAddAnyValue(Value&& value, utils::ValueType value_type) { values_.push_back(std::pair {std::move(value), value_type}); return values_.size() - 1; } template utils::IdType AddValue(const T& value, utils::ValueType value_type) { return ExplicitAddValue(std::move(value), value_type); } utils::IdType AddAnyValue(Value&& value, utils::ValueType value_type) { return ExplicitAddAnyValue(std::move(value), value_type); } 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; } void SetValueType(utils::IdType value_id, utils::ValueType value_type) { values_.at(value_id).second = value_type; } bool EqualValues(utils::IdType first_value, utils::IdType second_value) { return GetAnyValue(first_value)->Same(*GetAnyValue(second_value)); } bool AddValueRequirement(utils::IdType value, utils::IdType requrement) = delete; private: std::vector> values_; }; } // namespace info::value