129 lines
2.6 KiB
C++
129 lines
2.6 KiB
C++
#include <pslang/interpreter/value.hpp>
|
|
#include <pslang/interpreter/value_visitor.hpp>
|
|
#include <pslang/types/print.hpp>
|
|
|
|
#include <iomanip>
|
|
|
|
namespace pslang::interpreter
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
struct type_of_visitor
|
|
{
|
|
types::type operator()(unit_value const &)
|
|
{
|
|
return types::unit_type{};
|
|
}
|
|
|
|
template <typename T>
|
|
types::type operator()(primitive_value_base<T> const &)
|
|
{
|
|
return types::primitive_type(types::primitive_type_base<T>{});
|
|
}
|
|
|
|
types::type operator()(array_value const & value)
|
|
{
|
|
return types::array_type{.element_type = value.element_type, .size = value.elements.size()};
|
|
}
|
|
|
|
types::type operator()(struct_value const & value)
|
|
{
|
|
return *value.struct_type;
|
|
}
|
|
|
|
types::type operator()(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;
|
|
}
|
|
};
|
|
|
|
struct print_visitor
|
|
{
|
|
std::ostream & out;
|
|
|
|
void operator()(unit_value const &)
|
|
{
|
|
out << "unit";
|
|
}
|
|
|
|
template <typename T>
|
|
void operator()(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 operator()(array_value const & value)
|
|
{
|
|
out << "[";
|
|
for (std::size_t i = 0; i < value.elements.size(); ++i)
|
|
{
|
|
if (i > 0)
|
|
out << ", ";
|
|
apply(*this, *value.elements[i]);
|
|
}
|
|
out << "]";
|
|
}
|
|
|
|
void operator()(struct_value const & value)
|
|
{
|
|
out << "{";
|
|
bool first = true;
|
|
for (auto const & field : value.fields)
|
|
{
|
|
if (!first)
|
|
out << ", ";
|
|
first = false;
|
|
out << field.first << " = ";
|
|
apply(*this, *field.second);
|
|
}
|
|
out << "}";
|
|
}
|
|
|
|
void operator()(function_value const & value)
|
|
{
|
|
out << "func";
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
types::type type_of(value const & value)
|
|
{
|
|
return apply(type_of_visitor{}, value);
|
|
}
|
|
|
|
void print(std::ostream & out, value const & value)
|
|
{
|
|
apply(print_visitor{out}, value);
|
|
}
|
|
|
|
}
|