From 802b736e152c0832997c1f3ad1731f4397eedca3 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Tue, 9 May 2023 23:36:47 +0300 Subject: [PATCH] fixes, part of execute_visitor --- CMakeLists.txt | 1 + include/execute_visitor.hpp | 2 + include/values.hpp | 76 ++++++++++---- src/execute_visitor.cpp | 193 +++++++++++++++++++++++++++--------- src/type_check_visitor.cpp | 85 +++++++++++----- src/types.cpp | 1 - src/values.cpp | 79 +++++++++++++++ 7 files changed, 345 insertions(+), 92 deletions(-) create mode 100644 src/values.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 445fbf7..41dfcff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ include_directories(include add_executable(lang_interpreter src/main.cpp src/types.cpp + src/values.cpp src/global_info.cpp include/definitions.hpp src/visitor.cpp diff --git a/include/execute_visitor.hpp b/include/execute_visitor.hpp index 89e0dfb..6ead0d9 100644 --- a/include/execute_visitor.hpp +++ b/include/execute_visitor.hpp @@ -141,6 +141,7 @@ private: bool HandleCondition(Expression& condition, const BaseNode& base_node); void CollectTypeContext(const ParametrizedType& type); + void CheckPattern(Pattern& node, const BaseNode& base_node); template T* ExtractValue(utils::IdType value, const BaseNode& base_node) { @@ -169,6 +170,7 @@ private: std::optional active_loop_control_expression_; std::optional return_value_; // TODO: work outside block ?? std::optional is_const_definition_; + bool case_matched_; }; } // namespace interpreter diff --git a/include/values.hpp b/include/values.hpp index f62ab88..96cef0a 100644 --- a/include/values.hpp +++ b/include/values.hpp @@ -11,6 +11,8 @@ namespace info::value { +struct ValueManager; + struct Unit {}; struct InternalValue { @@ -27,6 +29,8 @@ public: } return &std::get(value); } + + std::optional GetFieldValue(const std::string& name); public: std::variant, utils::IdType>>&& fields) : fields(std::move(fields)) {} + 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: - VariantValue() = default; - VariantValue(utils::IdType value) // TupleValue ?? // TODO: add type & constructor?? - : value(value) {} + 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: - ReferenceToValue() = default; + explicit ReferenceToValue(ValueManager* value_manager) : value_manager_(value_manager) {} + ReferenceToValue(const std::vector& references, - utils::IdType value) - : references(references), value(value) {} + 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: - FunctionValue() = default; - FunctionValue(std::variant function) - : function(function) {} + 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: - ArrayValue() = default; + explicit ArrayValue(ValueManager* value_manager) : value_manager_(value_manager) {} + explicit ArrayValue(std::vector&& elements, - bool is_constant_size) - : elements(std::move(elements)), is_constant_size(is_constant_size) {} + 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: - OptionalValue() = default; - explicit OptionalValue(utils::IdType value) : value(value) {} + 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 ?? @@ -108,6 +149,7 @@ public: template explicit Value(const T& value) : value(value) {} // move ?? + std::optional GetFieldValue(const std::string& name); public: std::variantname.has_value()) { - // Visit(&node->name.value()); - } - Visitor::Visit(node->value); -} +void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {} // handled in TypeConstructorPattern // TODO void ExecuteVisitor::Visit(TypeConstructorPattern* node) { // TODO: not only tuples - Visit(node->constructor.get()); - for (auto& parameter : node->parameters) { - Visit(¶meter); + Visit(node->constructor.get()); // TODO: ?? check is same constructor_id ?? + for (auto& parameter : node->parameters) { // TODO: pass parameters separately + Visitor::Visit(parameter.value); // handle TypeConstructorPatternParameter } } -// TODO -void ExecuteVisitor::Visit(MatchCase* node) { - Visitor::Visit(node->value); - if (node->condition.has_value()) { - Visitor::Visit(node->condition.value()); - } - if (node->statement.has_value()) { - Visitor::Visit(node->statement.value()); - } -} +void ExecuteVisitor::Visit(MatchCase* node) {} // handeled in Match -// TODO void ExecuteVisitor::Visit(Match* node) { + context_manager_.EnterContext(); + Visitor::Visit(node->value); + + utils::IdType value = current_value_; + + bool case_choosen = false; + bool statement_visited = false; for (auto& match_case : node->matches) { - Visit(&match_case); + if (case_choosen) { + if (match_case.statement.has_value()) { + Visitor::Visit(match_case.statement.value()); + statement_visited = true; + break; + } + } else { + current_value_ = value; + case_matched_ = true; + + context_manager_.EnterContext(); + Visitor::Visit(node->value); + + if (case_matched_ && (match_case.condition.has_value() ? HandleCondition(match_case.condition.value(), match_case.base) : true)) { + case_choosen = true; + if (match_case.statement.has_value()) { + Visitor::Visit(match_case.statement.value()); + statement_visited = true; + break; + } + } else { + context_manager_.ExitContext(); + } + } } + + if (case_choosen) { + context_manager_.ExitContext(); + } + + if (statement_visited) { + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + } else { + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(context_manager_.GetValueManager()), + utils::ValueType::Tmp); + } + + context_manager_.ExitContext(); } void ExecuteVisitor::Visit(Condition* node) { + context_manager_.EnterContext(); + for (size_t i = 0; i < node->conditions.size(); ++i) { if (HandleCondition(node->conditions[i], node->base)) { Visitor::Visit(node->statements[i]); if (node->statements.size() == node->conditions.size()) { current_value_ = context_manager_.AddValue( - info::value::OptionalValue(current_value_), + info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), utils::ValueType::Tmp); // take value type from current_value_ ?? } return; // current_value_ passed from statement @@ -113,12 +145,16 @@ void ExecuteVisitor::Visit(Condition* node) { Visitor::Visit(node->statements[node->conditions.size()]); } else { current_value_ = context_manager_.AddValue( - info::value::OptionalValue(), + info::value::OptionalValue(context_manager_.GetValueManager()), utils::ValueType::Tmp); } + + context_manager_.ExitContext(); } void ExecuteVisitor::Visit(DoWhileLoop* node) { + context_manager_.EnterContext(); + std::vector result; do { Visitor::Visit(node->statement); @@ -135,11 +171,15 @@ void ExecuteVisitor::Visit(DoWhileLoop* node) { } while(HandleCondition(node->condition, node->base)); current_value_ = context_manager_.AddValue( - info::value::ArrayValue(std::move(result), false), + info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), utils::ValueType::Tmp); + + context_manager_.ExitContext(); } void ExecuteVisitor::Visit(WhileLoop* node) { + context_manager_.EnterContext(); + std::vector result; while(HandleCondition(node->condition, node->base)) { Visitor::Visit(node->statement); @@ -156,10 +196,14 @@ void ExecuteVisitor::Visit(WhileLoop* node) { } current_value_ = context_manager_.AddValue( - info::value::ArrayValue(std::move(result), false), + info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), utils::ValueType::Tmp); + + context_manager_.ExitContext(); } void ExecuteVisitor::Visit(ForLoop* node) { + context_manager_.EnterContext(); + std::vector result; // TODO: extend to different interval types (not only array) @@ -184,11 +228,15 @@ void ExecuteVisitor::Visit(ForLoop* node) { } current_value_ = context_manager_.AddValue( - info::value::ArrayValue(std::move(result), false), + info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), utils::ValueType::Tmp); + + context_manager_.ExitContext(); } void ExecuteVisitor::Visit(LoopLoop* node) { + context_manager_.EnterContext(); + std::vector result; while(true) { Visitor::Visit(node->statement); @@ -205,8 +253,10 @@ void ExecuteVisitor::Visit(LoopLoop* node) { } current_value_ = context_manager_.AddValue( - info::value::ArrayValue(std::move(result), false), + info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()), utils::ValueType::Tmp); + + context_manager_.ExitContext(); } // Statements, expressions, blocks, etc. ----------------- @@ -297,7 +347,7 @@ void ExecuteVisitor::Visit(ReferenceExpression* node) { utils::ValueType value_type = context_manager_.GetValueType(current_value_); current_value_ = context_manager_.AddValue( - info::value::ReferenceToValue(node->references, current_value_), + info::value::ReferenceToValue(node->references, current_value_, context_manager_.GetValueManager()), value_type); } @@ -376,29 +426,29 @@ void ExecuteVisitor::Visit(TupleExpression* node) { } current_value_ = context_manager_.AddValue( - info::value::TupleValue(std::move(fields)), + info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()), utils::ValueType::Tmp); } void ExecuteVisitor::Visit(VariantExpression* node) { // TODO: decide about return type (variant) - for (auto& expression : node->expressions) { - Visitor::Visit(expression); + for (size_t i = 0; i < node->expressions.size(); ++i) { + Visitor::Visit(node->expressions[i]); info::value::OptionalValue* expression_value = ExtractValue(current_value_, node->base); if (expression_value->value.has_value()) { current_value_ = context_manager_.AddValue( - info::value::VariantValue(expression_value->value.value()), + info::value::VariantValue(expression_value->value.value(), i, context_manager_.GetValueManager()), utils::ValueType::Tmp); current_value_ = context_manager_.AddValue( - info::value::OptionalValue(current_value_), + info::value::OptionalValue(current_value_, context_manager_.GetValueManager()), utils::ValueType::Tmp); return; } } current_value_ = context_manager_.AddValue( - info::value::OptionalValue(), + info::value::OptionalValue(context_manager_.GetValueManager()), utils::ValueType::Tmp); } @@ -407,21 +457,27 @@ void ExecuteVisitor::Visit(ReturnExpression* node) { return_value_ = current_value_; } -// TODO -void ExecuteVisitor::Visit(TypeConstructorParameter* node) { - if (node->name.has_value()) { - // Visit(&node->name.value()); - } - Visitor::Visit(node->value); -} -// TODO +void ExecuteVisitor::Visit(TypeConstructorParameter* node) {} // handled in TypeConstructor + + void ExecuteVisitor::Visit(TypeConstructor* node) { - // TODO: not only tuples - Visit(node->constructor.get()); + // TODO: support for non-tuples + std::vector, utils::IdType>> fields; + + // Visit(node->constructor.get()); // use parameters from type expression ?? + fields.reserve(node->parameters.size()); for (auto& parameter : node->parameters) { - Visit(¶meter); + Visitor::Visit(parameter.value); + // TODO: copy/move parameters + fields.push_back( + { parameter.name.has_value() ? std::optional(parameter.name.value().name) : std::nullopt, + current_value_ }); } + + current_value_ = context_manager_.AddValue( + info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()), + utils::ValueType::Tmp); } // TODO @@ -440,7 +496,7 @@ void ExecuteVisitor::Visit(ArrayExpression* node) { } current_value_ = context_manager_.AddValue( - info::value::ArrayValue(std::move(elements), true), // maybe size not fixed?? + info::value::ArrayValue(std::move(elements), true, context_manager_.GetValueManager()), // maybe size not fixed?? utils::ValueType::Tmp); } @@ -513,6 +569,7 @@ void ExecuteVisitor::Visit(TupleName* node) { // TODO: check } // TODO +// TODO: make variant of TupleValue void ExecuteVisitor::Visit(VariantName* node) { utils::IdType value = current_value_; @@ -522,6 +579,20 @@ void ExecuteVisitor::Visit(VariantName* node) { error_handling::HandleRuntimeError("Mismatched value types in variant variable definition", node->base); } + for (size_t i = 0; i < node->names.size(); ++i) { + if (i == maybe_variant_value.value()->current_constructor) { + // TODO if (fields_count.empty()) ... else ... + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(maybe_variant_value.value()->value, context_manager_.GetValueManager()), + utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? + } else { + current_value_ = context_manager_.AddValue( + info::value::OptionalValue(context_manager_.GetValueManager()), + utils::IsConstModifierToValueType(is_const_definition_.value())); + } + + Visitor::Visit(node->names[i]); + } // TODO: find out, which constructor used // set value to that constructor and None (empty OptionalValue) to others @@ -633,6 +704,34 @@ void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) { if (type.parameters[i]->type_id_.has_value()) { context_manager_.DefineLocalType(type_info.parameters[i].type, type.parameters[i]->type_id_.value()); + } + } +} + +// TODO +void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { + utils::IdType value = current_value_; + + switch (node.index()) { + case 0: + value = context_manager_.ToModifiedValue(value, utils::ValueType::Const); // ?? + if (!context_manager_.DefineVariable(std::get>(node)->name, + value)) { + error_handling::HandleRuntimeError("Can't redifine variable", base_node); + } + break; + case 1: + Visitor::Visit(*std::get>(node)); + if (!context_manager_.EqualValues(current_value_, value)) { // TODO + case_matched_ = false; + } + break; + case 2: + Visit(std::get>(node).get()); + break; + default: + // error + break; } } diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 24c71c8..7190a52 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -364,16 +364,15 @@ void TypeCheckVisitor::Visit(MatchCase* node) { error_handling::HandleTypecheckError("Match case condition is not bool expression", node->base); } - if (node->statement.has_value()) { - Visitor::Visit(node->statement.value()); - } - // current_type_ from statement is current_type_ for MatchCase + // IMPORTANT: statement visited in Match node->base.type_ = current_type_; } void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match // TODO: types can be different in block statement + context_manager_.EnterContext(); + utils::IdType type; bool is_type_found = false; @@ -381,17 +380,26 @@ void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match Visitor::Visit(node->value); utils::IdType value_type = current_type_; - for (size_t i = 0; i < node->matches.size(); ++i) { + // TODO: several matches with one statement typecheck <- check proposed solution + std::optional nearest_statement; + for (ssize_t i = (ssize_t)node->matches.size() - 1; i >= 0; --i) { // TODO: internal contexts ?? current_type_ = value_type; context_manager_.EnterContext(); Visit(&node->matches[i]); - context_manager_.ExitContext(); - if (!node->matches[i].statement.has_value()) { + if (node->matches[i].statement.has_value()) { + nearest_statement = &node->matches[i].statement.value(); + } + + if (!nearest_statement.has_value()) { continue; } + Visitor::Visit(*nearest_statement.value()); + + context_manager_.ExitContext(); + if (!is_type_found) { type = current_type_; is_type_found = true; @@ -408,10 +416,18 @@ void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match current_type_ = type; + current_type_ = context_manager_.AddValue( + info::type::OptionalType(current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); + + context_manager_.ExitContext(); + node->base.type_ = current_type_; } void TypeCheckVisitor::Visit(Condition* node) { + context_manager_.EnterContext(); + // TODO: types can be different in statement utils::IdType type; @@ -421,9 +437,8 @@ void TypeCheckVisitor::Visit(Condition* node) { error_handling::HandleTypecheckError("Condition statement condition is not bool expression", node->base); } - context_manager_.EnterContext(); Visitor::Visit(node->statements[i]); - context_manager_.ExitContext(); + if (i == 0) { type = current_type_; } else { @@ -434,9 +449,8 @@ void TypeCheckVisitor::Visit(Condition* node) { } if (node->statements.size() > node->conditions.size()) { - context_manager_.EnterContext(); Visitor::Visit(node->statements[node->conditions.size()]); - context_manager_.ExitContext(); + if (!context_manager_.EqualValues(type, current_type_)) { error_handling::HandleTypecheckError("Condition statement else have different type from other cases", node->base); } @@ -447,42 +461,52 @@ void TypeCheckVisitor::Visit(Condition* node) { utils::ValueType::Tmp); // ?? } + context_manager_.ExitContext(); + node->base.type_ = current_type_; } void TypeCheckVisitor::Visit(DoWhileLoop* node) { + context_manager_.EnterContext(); + Visitor::Visit(node->condition); if (!context_manager_.EqualValues(context_manager_.AddValue(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) { error_handling::HandleTypecheckError("Do while loop statement condition is not bool expression", node->base); } - context_manager_.EnterContext(); Visitor::Visit(node->statement); - context_manager_.ExitContext(); current_type_ = context_manager_.AddValue( info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), utils::ValueType::Tmp); + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; } void TypeCheckVisitor::Visit(WhileLoop* node) { + context_manager_.EnterContext(); + Visitor::Visit(node->condition); if (!context_manager_.EqualValues(context_manager_.AddValue(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) { error_handling::HandleTypecheckError("While loop statement condition is not bool expression", node->base); } - context_manager_.EnterContext(); Visitor::Visit(node->statement); - context_manager_.ExitContext(); current_type_ = context_manager_.AddValue( info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), utils::ValueType::Tmp); + context_manager_.ExitContext(); + node->base.type_ = current_type_; } void TypeCheckVisitor::Visit(ForLoop* node) { + context_manager_.EnterContext(); + Visitor::Visit(node->interval); std::optional maybe_interval_type = context_manager_.GetValue(current_type_); @@ -490,8 +514,6 @@ void TypeCheckVisitor::Visit(ForLoop* node) { error_handling::HandleTypecheckError("For loop interval type mismatch", node->base); } - context_manager_.EnterContext(); - current_type_ = context_manager_.ToModifiedValue(maybe_interval_type.value()->GetElementsType(), utils::IsConstModifierToValueType(node->variable_modifier)); @@ -501,22 +523,26 @@ void TypeCheckVisitor::Visit(ForLoop* node) { Visitor::Visit(node->statement); - context_manager_.ExitContext(); - current_type_ = context_manager_.AddValue( info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), utils::ValueType::Tmp); + + context_manager_.ExitContext(); + + node->base.type_ = current_type_; } void TypeCheckVisitor::Visit(LoopLoop* node) { context_manager_.EnterContext(); + Visitor::Visit(node->statement); - context_manager_.ExitContext(); current_type_ = context_manager_.AddValue( info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), utils::ValueType::Tmp); + context_manager_.ExitContext(); + node->base.type_ = current_type_; } @@ -897,9 +923,9 @@ void TypeCheckVisitor::Visit(VariantExpression* node) { std::nullopt), utils::ValueType::Tmp); - current_type_ = context_manager_.AddValue(info::type::OptionalType(current_type_, - context_manager_.GetValueManager()), - utils::ValueType::Tmp); + current_type_ = context_manager_.AddValue( + info::type::OptionalType(current_type_, context_manager_.GetValueManager()), + utils::ValueType::Tmp); node->base.type_ = current_type_; } @@ -1134,7 +1160,9 @@ void TypeCheckVisitor::Visit(VariantName* node) { for (size_t i = 0; i < node->names.size(); ++i) { if (maybe_type_value.value()->GetConstructors()[i].GetFields().empty()) { current_type_ = context_manager_.AddValue( - info::type::OptionalType(context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp), context_manager_.GetValueManager()), + info::type::OptionalType( + context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp), + context_manager_.GetValueManager()), utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? } else { info::type::TupleType constructor_type_value = maybe_type_value.value()->GetConstructors()[i]; @@ -1408,12 +1436,15 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) { switch (node.index()) { case 0: - context_manager_.DefineVariable(std::get>(node)->name, - value_type); + value_type = context_manager_.ToModifiedValue(value_type, utils::ValueType::Const); // ?? + if (!context_manager_.DefineVariable(std::get>(node)->name, + value_type)) { + error_handling::HandleTypecheckError("Can't redifine variable", base_node); + } break; case 1: Visitor::Visit(*std::get>(node)); - if (context_manager_.EqualValues(current_type_, value_type)) { // TODO: better solution ?? + if (!context_manager_.EqualValues(current_type_, value_type)) { // TODO: better solution ?? error_handling::HandleTypecheckError("Literal and value have different types", base_node); } break; diff --git a/src/types.cpp b/src/types.cpp index f2441ea..7e4ef44 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1,6 +1,5 @@ // for clangd #include "../include/types.hpp" -#include namespace info::type { diff --git a/src/values.cpp b/src/values.cpp new file mode 100644 index 0000000..26a531a --- /dev/null +++ b/src/values.cpp @@ -0,0 +1,79 @@ +// for clangd +#include "../include/values.hpp" + +namespace info::value { + +std::optional InternalValue::GetFieldValue(const std::string& name) { + return std::nullopt; +} + +// + +std::optional TupleValue::GetFieldValue(const std::string& name) { + for (size_t i = 0; i < fields.size(); ++i) { // TODO: optimize?? + if (fields[i].first.has_value() && fields[i].first.value() == name) { + return fields[i].second; + } + } + return std::nullopt; +} + +// + +std::optional VariantValue::GetFieldValue(const std::string& name) { + return value_manager_->GetAnyValue(value)->GetFieldValue(name); // TODO: TupleType ?? +} + +// + +std::optional ReferenceToValue::GetFieldValue(const std::string& name) { + return value_manager_->GetAnyValue(value)->GetFieldValue(name); +} + +// + +std::optional FunctionValue::GetFieldValue(const std::string& name) { + return std::nullopt; +} + +// + +std::optional ArrayValue::GetFieldValue(const std::string& name) { + return std::nullopt; +} + +// + +std::optional OptionalValue::GetFieldValue(const std::string& name) { + return std::nullopt; +} + +// + +std::optional Value::GetFieldValue(const std::string& name) { + size_t index = value.index(); + + switch (index) { + case 0: + return std::get(value).GetFieldValue(name); + case 1: + return std::get(value).GetFieldValue(name); + case 2: + return std::get(value).GetFieldValue(name); + case 3: + return std::get(value).GetFieldValue(name); + case 4: + return std::get(value).GetFieldValue(name); + case 5: + return std::get(value).GetFieldValue(name); + case 6: + return std::get(value).GetFieldValue(name); + default: + // error + break; + } + + return std::nullopt; +} + +}; // namespace info::value