Add interpreter::value_visitor

This commit is contained in:
Nikita Lisitsa 2025-12-20 15:07:45 +03:00
parent 8c07e1950b
commit 83b4d23ab2
2 changed files with 165 additions and 105 deletions

View file

@ -0,0 +1,71 @@
#pragma once
#include <pslang/interpreter/value.hpp>
namespace pslang::interpreter
{
namespace detail
{
template <typename Visitor>
struct const_value_visitor_helper
{
Visitor & visitor;
template <typename Value>
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 <typename Visitor>
struct value_visitor_helper
{
Visitor & visitor;
template <typename Value>
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 <typename Visitor>
auto apply(Visitor && visitor, value const & value)
{
detail::const_value_visitor_helper<Visitor> helper{visitor};
return helper(value);
}
template <typename Visitor>
auto apply(Visitor && visitor, value & value)
{
detail::value_visitor_helper<Visitor> helper{visitor};
return helper(value);
}
}

View file

@ -1,4 +1,5 @@
#include <pslang/interpreter/value.hpp> #include <pslang/interpreter/value.hpp>
#include <pslang/interpreter/value_visitor.hpp>
#include <pslang/types/print.hpp> #include <pslang/types/print.hpp>
#include <iomanip> #include <iomanip>
@ -9,33 +10,30 @@ namespace pslang::interpreter
namespace namespace
{ {
types::type type_of_impl(unit_value const &) struct type_of_visitor
{
types::type operator()(unit_value const &)
{ {
return types::unit_type{}; return types::unit_type{};
} }
template <typename T> template <typename T>
types::type type_of_impl(primitive_value_base<T> const &) types::type operator()(primitive_value_base<T> const &)
{ {
return types::primitive_type(types::primitive_type_base<T>{}); return types::primitive_type(types::primitive_type_base<T>{});
} }
types::type type_of_impl(primitive_value const & value) types::type operator()(array_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()}; return types::array_type{.element_type = value.element_type, .size = value.elements.size()};
} }
types::type type_of_impl(struct_value const & value) types::type operator()(struct_value const & value)
{ {
return *value.struct_type; return *value.struct_type;
} }
types::type type_of_impl(function_value const & value) types::type operator()(function_value const & value)
{ {
types::function_type result; types::function_type result;
for (auto const & argument : value.arguments) for (auto const & argument : value.arguments)
@ -43,19 +41,19 @@ namespace pslang::interpreter
result.result = value.return_type; result.result = value.return_type;
return result; return result;
} }
};
types::type type_of_impl(value const & value) struct print_visitor
{ {
return std::visit([](auto const & value){ return type_of_impl(value); }, value); std::ostream & out;
}
void print_impl(std::ostream & out, unit_value const &) void operator()(unit_value const &)
{ {
out << "unit"; out << "unit";
} }
template <typename T> template <typename T>
void print_impl(std::ostream & out, primitive_value_base<T> const & value) void operator()(primitive_value_base<T> const & value)
{ {
if constexpr (std::is_same_v<T, bool>) if constexpr (std::is_same_v<T, bool>)
{ {
@ -83,24 +81,19 @@ namespace pslang::interpreter
} }
} }
void print_impl(std::ostream & out, primitive_value const & value) void operator()(array_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 << "["; out << "[";
for (std::size_t i = 0; i < value.elements.size(); ++i) for (std::size_t i = 0; i < value.elements.size(); ++i)
{ {
if (i > 0) if (i > 0)
out << ", "; out << ", ";
print(out, *value.elements[i]); apply(*this, *value.elements[i]);
} }
out << "]"; out << "]";
} }
void print_impl(std::ostream & out, struct_value const & value) void operator()(struct_value const & value)
{ {
out << "{"; out << "{";
bool first = true; bool first = true;
@ -110,31 +103,27 @@ namespace pslang::interpreter
out << ", "; out << ", ";
first = false; first = false;
out << field.first << " = "; out << field.first << " = ";
print(out, *field.second); apply(*this, *field.second);
} }
out << "}"; out << "}";
} }
void print_impl(std::ostream & out, function_value const & value) void operator()(function_value const & value)
{ {
out << "func"; out << "func";
} }
};
void print_impl(std::ostream & out, value const & value)
{
std::visit([&](auto const & value){ return print_impl(out, value); }, value);
}
} }
types::type type_of(value const & value) 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) void print(std::ostream & out, value const & value)
{ {
print_impl(out, value); apply(print_visitor{out}, value);
} }
} }