From 83b4d23ab2d0b45eeaaa0ca2dbf44f6f239853d8 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 20 Dec 2025 15:07:45 +0300 Subject: [PATCH] Add interpreter::value_visitor --- .../pslang/interpreter/value_visitor.hpp | 71 +++++++ libs/interpreter/source/value.cpp | 199 +++++++++--------- 2 files changed, 165 insertions(+), 105 deletions(-) create mode 100644 libs/interpreter/include/pslang/interpreter/value_visitor.hpp diff --git a/libs/interpreter/include/pslang/interpreter/value_visitor.hpp b/libs/interpreter/include/pslang/interpreter/value_visitor.hpp new file mode 100644 index 0000000..8f05b74 --- /dev/null +++ b/libs/interpreter/include/pslang/interpreter/value_visitor.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include + +namespace pslang::interpreter +{ + + namespace detail + { + + template + struct const_value_visitor_helper + { + Visitor & visitor; + + template + auto operator()(Value const & value) + { + return visitor(value); + } + + auto operator()(value const & value) + { + return std::visit(*this, value); + } + + auto operator()(primitive_value const & value) + { + return std::visit(*this, value); + } + }; + + template + struct value_visitor_helper + { + Visitor & visitor; + + template + auto operator()(Value & value) + { + return visitor(value); + } + + auto operator()(value & value) + { + return std::visit(*this, value); + } + + auto operator()(primitive_value & value) + { + return std::visit(*this, value); + } + }; + + } + + template + auto apply(Visitor && visitor, value const & value) + { + detail::const_value_visitor_helper helper{visitor}; + return helper(value); + } + + template + auto apply(Visitor && visitor, value & value) + { + detail::value_visitor_helper helper{visitor}; + return helper(value); + } + +} diff --git a/libs/interpreter/source/value.cpp b/libs/interpreter/source/value.cpp index 621ade1..cffcd61 100644 --- a/libs/interpreter/source/value.cpp +++ b/libs/interpreter/source/value.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -9,132 +10,120 @@ namespace pslang::interpreter namespace { - types::type type_of_impl(unit_value const &) + struct type_of_visitor { - return types::unit_type{}; - } - - template - types::type type_of_impl(primitive_value_base const &) - { - return types::primitive_type(types::primitive_type_base{}); - } - - types::type type_of_impl(primitive_value const & value) - { - return std::visit([](auto const & value){ return type_of_impl(value); }, value); - } - - types::type type_of_impl(array_value const & value) - { - return types::array_type{.element_type = value.element_type, .size = value.elements.size()}; - } - - types::type type_of_impl(struct_value const & value) - { - return *value.struct_type; - } - - types::type type_of_impl(function_value const & value) - { - types::function_type result; - for (auto const & argument : value.arguments) - result.arguments.push_back(argument.type); - result.result = value.return_type; - return result; - } - - types::type type_of_impl(value const & value) - { - return std::visit([](auto const & value){ return type_of_impl(value); }, value); - } - - void print_impl(std::ostream & out, unit_value const &) - { - out << "unit"; - } - - template - void print_impl(std::ostream & out, primitive_value_base const & value) - { - if constexpr (std::is_same_v) + types::type operator()(unit_value const &) { - out << (value.value ? "true" : "false"); + return types::unit_type{}; } - else if constexpr (std::is_integral_v && std::is_signed_v) - { - out << (std::int64_t)value.value; - } - else if constexpr (std::is_integral_v && std::is_unsigned_v) - { - out << (std::uint64_t)value.value; - } - else if constexpr (std::is_same_v) - { - out << std::setprecision(7) << value.value; - } - else if constexpr (std::is_same_v) - { - out << std::setprecision(15) << value.value; - } - else - { - out << "(unknown)"; - } - } - void print_impl(std::ostream & out, primitive_value const & value) - { - std::visit([&](auto const & value){ return print_impl(out, value); }, value); - } - - void print_impl(std::ostream & out, array_value const & value) - { - out << "["; - for (std::size_t i = 0; i < value.elements.size(); ++i) + template + types::type operator()(primitive_value_base const &) { - if (i > 0) - out << ", "; - print(out, *value.elements[i]); + return types::primitive_type(types::primitive_type_base{}); } - out << "]"; - } - void print_impl(std::ostream & out, struct_value const & value) - { - out << "{"; - bool first = true; - for (auto const & field : value.fields) + types::type operator()(array_value const & value) { - if (!first) - out << ", "; - first = false; - out << field.first << " = "; - print(out, *field.second); + return types::array_type{.element_type = value.element_type, .size = value.elements.size()}; } - out << "}"; - } - void print_impl(std::ostream & out, function_value const & value) - { - out << "func"; - } + types::type operator()(struct_value const & value) + { + return *value.struct_type; + } - void print_impl(std::ostream & out, value const & value) + types::type operator()(function_value const & value) + { + types::function_type result; + for (auto const & argument : value.arguments) + result.arguments.push_back(argument.type); + result.result = value.return_type; + return result; + } + }; + + struct print_visitor { - std::visit([&](auto const & value){ return print_impl(out, value); }, value); - } + std::ostream & out; + + void operator()(unit_value const &) + { + out << "unit"; + } + + template + void operator()(primitive_value_base const & value) + { + if constexpr (std::is_same_v) + { + out << (value.value ? "true" : "false"); + } + else if constexpr (std::is_integral_v && std::is_signed_v) + { + out << (std::int64_t)value.value; + } + else if constexpr (std::is_integral_v && std::is_unsigned_v) + { + out << (std::uint64_t)value.value; + } + else if constexpr (std::is_same_v) + { + out << std::setprecision(7) << value.value; + } + else if constexpr (std::is_same_v) + { + out << std::setprecision(15) << value.value; + } + else + { + out << "(unknown)"; + } + } + + void operator()(array_value const & value) + { + out << "["; + for (std::size_t i = 0; i < value.elements.size(); ++i) + { + if (i > 0) + out << ", "; + apply(*this, *value.elements[i]); + } + out << "]"; + } + + void operator()(struct_value const & value) + { + out << "{"; + bool first = true; + for (auto const & field : value.fields) + { + if (!first) + out << ", "; + first = false; + out << field.first << " = "; + apply(*this, *field.second); + } + out << "}"; + } + + void operator()(function_value const & value) + { + out << "func"; + } + }; } types::type type_of(value const & value) { - return type_of_impl(value); + return apply(type_of_visitor{}, value); } void print(std::ostream & out, value const & value) { - print_impl(out, value); + apply(print_visitor{out}, value); } }