Refactor type visitor

This commit is contained in:
Nikita Lisitsa 2025-12-20 15:40:02 +03:00
parent d37c5b8754
commit 1f8c73614c
3 changed files with 64 additions and 83 deletions

View file

@ -9,40 +9,43 @@ namespace pslang::interpreter
{ {
struct zero_value_visitor struct zero_value_visitor
: types::const_visitor<zero_value_visitor>
{ {
interpreter::context & context; interpreter::context & context;
value operator()(types::unit_type const &) using const_visitor::apply;
value apply(types::unit_type const &)
{ {
return unit_value{}; return unit_value{};
} }
template <typename T> template <typename T>
value operator()(types::primitive_type_base<T> const &) value apply(types::primitive_type_base<T> const &)
{ {
return primitive_value{primitive_value_base<T>{.value = {}}}; return primitive_value{primitive_value_base<T>{.value = {}}};
} }
value operator()(types::array_type const & array_type) value apply(types::array_type const & array_type)
{ {
array_value result{.element_type = array_type.element_type}; array_value result{.element_type = array_type.element_type};
for (std::uint64_t i = 0; i < array_type.size; ++i) for (std::uint64_t i = 0; i < array_type.size; ++i)
result.elements.push_back(std::make_unique<value>(types::apply(*this, *array_type.element_type))); result.elements.push_back(std::make_unique<value>(apply(*array_type.element_type)));
return std::move(result); return std::move(result);
} }
value operator()(types::function_type const &) value apply(types::function_type const &)
{ {
throw std::runtime_error("Cannot zero-initialize a function type"); throw std::runtime_error("Cannot zero-initialize a function type");
} }
value operator()(types::named_type const & named_type) value apply(types::named_type const & named_type)
{ {
auto const & struct_data = context.scope_stack.at(named_type.level).structs.at(named_type.name); auto const & struct_data = context.scope_stack.at(named_type.level).structs.at(named_type.name);
struct_value result{.struct_type = std::make_unique<types::type>(named_type)}; struct_value result{.struct_type = std::make_unique<types::type>(named_type)};
for (auto const & field : struct_data.fields) for (auto const & field : struct_data.fields)
result.fields[field.name] = std::make_unique<value>(types::apply(*this, *field.type)); result.fields[field.name] = std::make_unique<value>(apply(*field.type));
return std::move(result); return std::move(result);
} }
}; };
@ -74,7 +77,7 @@ namespace pslang::interpreter
value zero_value(context & context, types::type const & type) value zero_value(context & context, types::type const & type)
{ {
return types::apply(zero_value_visitor{context}, type); return zero_value_visitor{{}, context}.apply(type);
} }
} }

View file

@ -5,67 +5,42 @@
namespace pslang::types namespace pslang::types
{ {
namespace detail template <typename Derived>
struct const_visitor
{ {
Derived & derived()
template <typename Visitor>
struct const_visitor_helper
{ {
Visitor & visitor; return static_cast<Derived &>(*this);
template <typename Type>
auto operator()(Type const & type)
{
return visitor(type);
} }
auto operator()(types::primitive_type const & type) auto apply(types::primitive_type const & type)
{ {
return std::visit(*this, type); return std::visit([this](auto const & type){ return derived().apply(type); }, type);
} }
auto operator()(types::type const & type) auto apply(types::type const & type)
{ {
return std::visit(*this, type); return std::visit([this](auto const & type){ return derived().apply(type); }, type);
} }
}; };
template <typename Visitor> template <typename Derived>
struct visitor_helper struct visitor
{ {
Visitor & visitor; Derived & derived()
template <typename Type>
auto operator()(Type & type)
{ {
return visitor(type); return static_cast<Derived &>(*this);
} }
auto operator()(types::primitive_type & type) auto apply(types::primitive_type & type)
{ {
return std::visit(*this, type); return std::visit([this](auto & type){ return derived().apply(type); }, type);
} }
auto operator()(types::type & type) auto apply(types::type & type)
{ {
return std::visit(*this, type); return std::visit([this](auto & type){ return derived().apply(type); }, type);
} }
}; };
}
template <typename Visitor>
auto apply(Visitor && visitor, type const & type)
{
detail::const_visitor_helper<Visitor> helper{visitor};
return helper(type);
}
template <typename Visitor>
auto apply(Visitor && visitor, type & type)
{
detail::visitor_helper<Visitor> helper{visitor};
return helper(type);
}
} }

View file

@ -8,82 +8,85 @@ namespace pslang::types
{ {
struct print_visitor struct print_visitor
: const_visitor<print_visitor>
{ {
std::ostream & out; std::ostream & out;
void operator()(unit_type const & type) using const_visitor::apply;
void apply(unit_type const & type)
{ {
out << "unit"; out << "unit";
} }
void operator()(bool_type const &) void apply(bool_type const &)
{ {
out << "bool"; out << "bool";
} }
void operator()(i8_type const &) void apply(i8_type const &)
{ {
out << "i8"; out << "i8";
} }
void operator()(u8_type const &) void apply(u8_type const &)
{ {
out << "u8"; out << "u8";
} }
void operator()(i16_type const &) void apply(i16_type const &)
{ {
out << "i16"; out << "i16";
} }
void operator()(u16_type const &) void apply(u16_type const &)
{ {
out << "u16"; out << "u16";
} }
void operator()(i32_type const &) void apply(i32_type const &)
{ {
out << "i32"; out << "i32";
} }
void operator()(u32_type const &) void apply(u32_type const &)
{ {
out << "u32"; out << "u32";
} }
void operator()(i64_type const &) void apply(i64_type const &)
{ {
out << "i64"; out << "i64";
} }
void operator()(u64_type const &) void apply(u64_type const &)
{ {
out << "u64"; out << "u64";
} }
void operator()(f32_type const &) void apply(f32_type const &)
{ {
out << "f32"; out << "f32";
} }
void operator()(f64_type const &) void apply(f64_type const &)
{ {
out << "f64"; out << "f64";
} }
void operator()(array_type const & type) void apply(array_type const & type)
{ {
apply(*this, *type.element_type); apply(*type.element_type);
out << "[" << type.size << "]"; out << "[" << type.size << "]";
} }
void operator()(function_type const & type) void apply(function_type const & type)
{ {
if (type.arguments.size() == 1) if (type.arguments.size() == 1)
{ {
apply(*this, *type.arguments.front()); apply(*type.arguments.front());
out << " -> "; out << " -> ";
apply(*this, *type.result); apply(*type.result);
return; return;
} }
@ -93,13 +96,13 @@ namespace pslang::types
{ {
if (!first) out << ", "; if (!first) out << ", ";
first = false; first = false;
apply(*this, *argument); apply(*argument);
} }
out << ") -> "; out << ") -> ";
apply(*this, *type.result); apply(*type.result);
} }
void operator()(named_type const & type) void apply(named_type const & type)
{ {
out << type.name; out << type.name;
} }
@ -109,7 +112,7 @@ namespace pslang::types
void print(std::ostream & out, type const & type) void print(std::ostream & out, type const & type)
{ {
apply(print_visitor{out}, type); print_visitor{{}, out}.apply(type);
} }
} }