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
: types::const_visitor<zero_value_visitor>
{
interpreter::context & context;
value operator()(types::unit_type const &)
using const_visitor::apply;
value apply(types::unit_type const &)
{
return unit_value{};
}
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 = {}}};
}
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};
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);
}
value operator()(types::function_type const &)
value apply(types::function_type const &)
{
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);
struct_value result{.struct_type = std::make_unique<types::type>(named_type)};
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);
}
};
@ -74,7 +77,7 @@ namespace pslang::interpreter
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 detail
template <typename Derived>
struct const_visitor
{
template <typename Visitor>
struct const_visitor_helper
Derived & derived()
{
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)
{
return std::visit(*this, type);
}
auto operator()(types::type const & type)
{
return std::visit(*this, type);
}
};
template <typename Visitor>
struct visitor_helper
auto apply(types::primitive_type const & type)
{
Visitor & visitor;
return std::visit([this](auto const & type){ return derived().apply(type); }, type);
}
template <typename Type>
auto operator()(Type & type)
{
return visitor(type);
}
auto apply(types::type const & type)
{
return std::visit([this](auto const & type){ return derived().apply(type); }, type);
}
};
auto operator()(types::primitive_type & type)
{
return std::visit(*this, type);
}
auto operator()(types::type & type)
{
return std::visit(*this, type);
}
};
}
template <typename Visitor>
auto apply(Visitor && visitor, type const & type)
template <typename Derived>
struct visitor
{
detail::const_visitor_helper<Visitor> helper{visitor};
return helper(type);
}
Derived & derived()
{
return static_cast<Derived &>(*this);
}
template <typename Visitor>
auto apply(Visitor && visitor, type & type)
{
detail::visitor_helper<Visitor> helper{visitor};
return helper(type);
}
auto apply(types::primitive_type & type)
{
return std::visit([this](auto & type){ return derived().apply(type); }, type);
}
auto apply(types::type & type)
{
return std::visit([this](auto & type){ return derived().apply(type); }, type);
}
};
}

View file

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