#include #include #include namespace pslang::interpreter { namespace { types::type type_of_impl(unit_value const &) { return types::unit_type{}; } template types::type type_of_impl(primitive_value_base const &) { return types::primitive_type(types::primitive_type_base{}); } 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 void print_impl(std::ostream & out, primitive_value_base const & value) { if constexpr (std::is_same_v) { out << (value.value ? "true" : "false"); } else if constexpr (std::is_integral_v && std::is_signed_v) { out << (std::int64_t)value.value; } else if constexpr (std::is_integral_v && std::is_unsigned_v) { out << (std::uint64_t)value.value; } else if constexpr (std::is_same_v) { out << std::setprecision(7) << value.value; } else if constexpr (std::is_same_v) { 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); } }