#include "Printer.h" #include "third-party/fmt/core.h" namespace pretty_print { namespace { // the integer representation is used here instead, wouldn't want really long numbers const std::unordered_set banned_floats = {}; // print these floats (shown as ints here) as a named constant instead const std::unordered_map const_floats = {{0x40490fda, "PI"}, {0xc0490fda, "MINUS_PI"}}; } // namespace /*! * Print a float in a nice representation if possible, or an exact 32-bit integer constant to * be reinterpreted. */ goos::Object float_representation(float value) { u32 int_value; memcpy(&int_value, &value, 4); u8 exp = (int_value >> 23) & 0xff; u32 mant = int_value & 0x7fffff; if ((exp == 0 && mant != 0) || exp == 0xff) { // lg::warn("PS2-incompatible float (0x{:08X}) detected! Writing as the-as cast.", int_value); return pretty_print::build_list("the-as", "float", fmt::format("#x{:x}", int_value)); } else if (const_floats.find(int_value) != const_floats.end()) { return pretty_print::to_symbol(const_floats.at(int_value)); } else if (banned_floats.find(int_value) == banned_floats.end()) { return goos::Object::make_float(value); } else { return pretty_print::build_list("the-as", "float", fmt::format("#x{:x}", int_value)); } } std::unique_ptr pretty_printer_reader; goos::Reader& get_pretty_printer_reader() { if (!pretty_printer_reader) { pretty_printer_reader = std::make_unique(); } return *pretty_printer_reader; } goos::Object to_symbol(const std::string& str) { return goos::SymbolObject::make_new(get_pretty_printer_reader().symbolTable, str); } goos::Object build_list(const std::string& str) { return build_list(to_symbol(str)); } goos::Object build_list(const goos::Object& obj) { return goos::PairObject::make_new(obj, goos::Object::make_empty_list()); } goos::Object build_list(const std::vector& objects) { if (objects.empty()) { return goos::Object::make_empty_list(); } else { return build_list(objects.data(), objects.size()); } } // build a list out of an array of forms goos::Object build_list(const goos::Object* objects, int count) { ASSERT(count); auto car = objects[0]; goos::Object cdr; if (count - 1) { cdr = build_list(objects + 1, count - 1); } else { cdr = goos::Object::make_empty_list(); } return goos::PairObject::make_new(car, cdr); } // build a list out of a vector of strings that are converted to symbols goos::Object build_list(const std::vector& symbols) { if (symbols.empty()) { return goos::Object::make_empty_list(); } std::vector f; f.reserve(symbols.size()); for (auto& x : symbols) { f.push_back(to_symbol(x)); } return build_list(f.data(), f.size()); } void append(goos::Object& _in, const goos::Object& add) { auto* in = &_in; while (in->is_pair() && !in->as_pair()->cdr.is_empty_list()) { in = &in->as_pair()->cdr; } if (!in->is_pair()) { ASSERT(false); // invalid list } in->as_pair()->cdr = add; } } // namespace pretty_print