#include #include #include #include namespace pslang::interpreter { namespace { struct type_of_visitor { types::type operator()(unit_value const &) { return types::unit_type{}; } template types::type operator()(primitive_value_base const &) { return types::primitive_type(types::primitive_type_base{}); } 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; } types::type operator()(foreign_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 void operator()(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 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"; } void operator()(foreign_function_value const & value) { out << "foreign 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); } }