pslang/libs/interpreter/source/value.cpp

140 lines
3 KiB
C++

#include <pslang/interpreter/value.hpp>
#include <pslang/types/print.hpp>
#include <iomanip>
namespace pslang::interpreter
{
namespace
{
types::type type_of_impl(unit_value const &)
{
return types::unit_type{};
}
template <typename T>
types::type type_of_impl(primitive_value_base<T> const &)
{
return types::primitive_type(types::primitive_type_base<T>{});
}
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 <typename T>
void print_impl(std::ostream & out, primitive_value_base<T> const & value)
{
if constexpr (std::is_same_v<T, bool>)
{
out << (value.value ? "true" : "false");
}
else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>)
{
out << (std::int64_t)value.value;
}
else if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>)
{
out << (std::uint64_t)value.value;
}
else if constexpr (std::is_same_v<T, float>)
{
out << std::setprecision(7) << value.value;
}
else if constexpr (std::is_same_v<T, double>)
{
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)
{
if (i > 0)
out << ", ";
print(out, *value.elements[i]);
}
out << "]";
}
void print_impl(std::ostream & out, struct_value const & value)
{
out << "{";
bool first = true;
for (auto const & field : value.fields)
{
if (!first)
out << ", ";
first = false;
out << field.first << " = ";
print(out, *field.second);
}
out << "}";
}
void print_impl(std::ostream & out, function_value const & value)
{
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)
{
return type_of_impl(value);
}
void print(std::ostream & out, value const & value)
{
print_impl(out, value);
}
}