#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: explicit TupleValue(ValueManager* value_manager) : value_manager_(value_manager) {} explicit 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_; }; struct VariantValue { public: explicit VariantValue(ValueManager* value_manager) : value_manager_(value_manager) {} // TupleValue ?? // TODO: add type?? VariantValue(utils::IdType value, size_t current_constructor, ValueManager* value_manager) : value(value), current_constructor(current_constructor), value_manager_(value_manager) {} public: utils::IdType value; size_t current_constructor; std::optional GetFieldValue(const std::string& name); private: ValueManager* value_manager_; }; struct ReferenceToValue { public: explicit ReferenceToValue(ValueManager* value_manager) : value_manager_(value_manager) {} 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_; }; struct FunctionValue { public: explicit FunctionValue(ValueManager* value_manager) : value_manager_(value_manager) {} 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_; }; struct ArrayValue { public: explicit ArrayValue(ValueManager* value_manager) : value_manager_(value_manager) {} explicit 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_; }; struct OptionalValue { public: explicit OptionalValue(ValueManager* value_manager) : value_manager_(value_manager) {} explicit OptionalValue(utils::IdType 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_; }; 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 EqualTypes(utils::IdType first_type, utils::IdType second_type) = delete; // TODO bool AddTypeRequirement(utils::IdType type, utils::IdType requrement) = delete; private: std::vector> values_; }; } // namespace info::value