Support zero (default) initialization for struct types

This commit is contained in:
Nikita Lisitsa 2025-12-20 15:18:48 +03:00
parent 83b4d23ab2
commit d37c5b8754
4 changed files with 71 additions and 16 deletions

View file

@ -54,4 +54,6 @@ namespace pslang::interpreter
void dump(std::ostream & out, context const & context);
value zero_value(context & context, types::type const & type);
}

View file

@ -1,9 +1,54 @@
#include <pslang/interpreter/context.hpp>
#include <pslang/types/type_visitor.hpp>
#include <pslang/types/print.hpp>
namespace pslang::interpreter
{
namespace
{
struct zero_value_visitor
{
interpreter::context & context;
value operator()(types::unit_type const &)
{
return unit_value{};
}
template <typename T>
value operator()(types::primitive_type_base<T> const &)
{
return primitive_value{primitive_value_base<T>{.value = {}}};
}
value operator()(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)));
return std::move(result);
}
value operator()(types::function_type const &)
{
throw std::runtime_error("Cannot zero-initialize a function type");
}
value operator()(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));
return std::move(result);
}
};
}
context empty_context()
{
context result;
@ -27,4 +72,9 @@ namespace pslang::interpreter
std::cout << std::flush;
}
value zero_value(context & context, types::type const & type)
{
return types::apply(zero_value_visitor{context}, type);
}
}

View file

@ -514,6 +514,9 @@ namespace pslang::interpreter
{
if (auto jt = it->structs.find(identifier->name); jt != it->structs.end())
{
if (function_call.arguments.empty())
return zero_value(context, types::named_type{.name = identifier->name, .level = identifier->level});
if (jt->second.fields.size() != function_call.arguments.size())
{
std::ostringstream os;

View file

@ -14,19 +14,19 @@ namespace pslang::types
Visitor & visitor;
template <typename Type>
void operator()(Type const & type)
auto operator()(Type const & type)
{
visitor(type);
return visitor(type);
}
void operator()(types::primitive_type const & type)
auto operator()(types::primitive_type const & type)
{
std::visit(*this, type);
return std::visit(*this, type);
}
void operator()(types::type const & type)
auto operator()(types::type const & type)
{
std::visit(*this, type);
return std::visit(*this, type);
}
};
@ -36,36 +36,36 @@ namespace pslang::types
Visitor & visitor;
template <typename Type>
void operator()(Type & type)
auto operator()(Type & type)
{
visitor(type);
return visitor(type);
}
void operator()(types::primitive_type & type)
auto operator()(types::primitive_type & type)
{
std::visit(*this, type);
return std::visit(*this, type);
}
void operator()(types::type & type)
auto operator()(types::type & type)
{
std::visit(*this, type);
return std::visit(*this, type);
}
};
}
template <typename Visitor>
void apply(Visitor && visitor, type const & type)
auto apply(Visitor && visitor, type const & type)
{
detail::const_visitor_helper<Visitor> helper{visitor};
helper(type);
return helper(type);
}
template <typename Visitor>
void apply(Visitor && visitor, type & type)
auto apply(Visitor && visitor, type & type)
{
detail::visitor_helper<Visitor> helper{visitor};
helper(type);
return helper(type);
}
}