diff --git a/.github/workflows/linux-workflow.yaml b/.github/workflows/linux-workflow.yaml index d243ff83e1..d8f0f7082f 100644 --- a/.github/workflows/linux-workflow.yaml +++ b/.github/workflows/linux-workflow.yaml @@ -25,7 +25,7 @@ jobs: runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.experimental }} # Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them. - timeout-minutes: 10 + timeout-minutes: 20 steps: # NOTE - useful for debugging diff --git a/common/goos/Object.cpp b/common/goos/Object.cpp index 1c6bb05bac..646b665488 100644 --- a/common/goos/Object.cpp +++ b/common/goos/Object.cpp @@ -87,8 +87,16 @@ std::string object_type_to_string(ObjectType type) { template <> std::string fixed_to_string(FloatType x) { char buff[256]; - sprintf(buff, "%.6f", x); - return {buff}; + s64 rounded = x; + bool exact_int = ((float)rounded) == x; + + if (exact_int) { + sprintf(buff, "%.1f", x); + return {buff}; + } else { + sprintf(buff, "%.6f", x); + return {buff}; + } } /*! diff --git a/common/goos/PrettyPrinter.cpp b/common/goos/PrettyPrinter.cpp index 1e8a0972c6..445ab046a4 100644 --- a/common/goos/PrettyPrinter.cpp +++ b/common/goos/PrettyPrinter.cpp @@ -25,10 +25,17 @@ const std::unordered_set allowed_floats = { * be reinterpreted. */ goos::Object float_representation(float value) { - int rounded = value; + s64 rounded = value; bool exact_int = ((float)rounded) == value; if (exact_int || allowed_floats.find(value) != allowed_floats.end()) { - return goos::Object::make_float(value); + auto result = goos::Object::make_float(value); + + // this is probably very slow for huge numbers of floats, but worth checking. + auto float_as_string = result.print(); + auto as_float_again = float(std::stod(float_as_string)); + assert(as_float_again == value); + + return result; } else { u32 int_value; memcpy(&int_value, &value, 4); diff --git a/common/type_system/Type.h b/common/type_system/Type.h index 6b36595e61..c6941ee0b0 100644 --- a/common/type_system/Type.h +++ b/common/type_system/Type.h @@ -300,6 +300,7 @@ class BitFieldType : public ValueType { bool lookup_field(const std::string& name, BitField* out) const; std::string print() const override; bool operator==(const Type& other) const override; + const std::vector& fields() const { return m_fields; } private: friend class TypeSystem; diff --git a/common/type_system/TypeFieldLookup.cpp b/common/type_system/TypeFieldLookup.cpp index a7f3c996bc..43c78348b9 100644 --- a/common/type_system/TypeFieldLookup.cpp +++ b/common/type_system/TypeFieldLookup.cpp @@ -109,9 +109,8 @@ bool TypeSystem::try_reverse_lookup_pointer(const FieldReverseLookupInput& input return false; } auto di = get_deref_info(input.base_type); - bool is_integer = - typecheck(TypeSpec("integer"), input.base_type.get_single_arg(), "", false, false); - bool is_basic = typecheck(TypeSpec("basic"), input.base_type.get_single_arg(), "", false, false); + bool is_integer = tc(TypeSpec("integer"), input.base_type.get_single_arg()); + bool is_basic = tc(TypeSpec("basic"), input.base_type.get_single_arg()); assert(di.mem_deref); // it's accessing a pointer. auto elt_type = di.result_type; if (input.stride) { @@ -205,9 +204,8 @@ bool TypeSystem::try_reverse_lookup_array(const FieldReverseLookupInput& input, // this is the data type - (pointer elt-type). this is stored at an offset of ARRAY_DATA_OFFSET. auto array_data_type = make_pointer_typespec(input.base_type.get_single_arg()); auto di = get_deref_info(array_data_type); - bool is_integer = - typecheck(TypeSpec("integer"), input.base_type.get_single_arg(), "", false, false); - bool is_basic = typecheck(TypeSpec("basic"), input.base_type.get_single_arg(), "", false, false); + bool is_integer = tc(TypeSpec("integer"), input.base_type.get_single_arg()); + bool is_basic = tc(TypeSpec("basic"), input.base_type.get_single_arg()); assert(di.mem_deref); // it's accessing a pointer. auto elt_type = di.result_type; if (input.stride) { @@ -398,8 +396,8 @@ bool TypeSystem::try_reverse_lookup_other(const FieldReverseLookupInput& input, // (pointer ) TypeSpec loc_type = make_pointer_typespec(field_deref.type); auto di = get_deref_info(loc_type); - bool is_integer = typecheck(TypeSpec("integer"), field_deref.type, "", false, false); - bool is_basic = typecheck(TypeSpec("basic"), field_deref.type, "", false, false); + bool is_integer = tc(TypeSpec("integer"), field_deref.type); + bool is_basic = tc(TypeSpec("basic"), field_deref.type); if (!deref_matches(di, input.deref.value(), is_integer, is_basic)) { continue; // try another field! } diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index e4b403fb38..331833094e 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -127,7 +127,7 @@ DerefInfo TypeSystem::get_deref_info(const TypeSpec& ts) const { info.reg = RegClass::GPR_64; info.mem_deref = true; - if (typecheck(TypeSpec("float"), ts, "", false, false)) { + if (tc(TypeSpec("float"), ts)) { info.reg = RegClass::FLOAT; } @@ -1008,6 +1008,10 @@ void TypeSystem::builtin_structure_inherit(StructureType* st) { st->inherit(get_type_of_type(st->get_parent())); } +bool TypeSystem::tc(const TypeSpec& expected, const TypeSpec& actual) const { + return typecheck_and_throw(expected, actual, "", false, false); +} + /*! * Main compile-time type check! * @param expected - the expected type @@ -1017,11 +1021,11 @@ void TypeSystem::builtin_structure_inherit(StructureType* st) { * @param throw_on_error - throw a std::runtime_error on failure if set. * @return if the type check passes */ -bool TypeSystem::typecheck(const TypeSpec& expected, - const TypeSpec& actual, - const std::string& error_source_name, - bool print_on_error, - bool throw_on_error) const { +bool TypeSystem::typecheck_and_throw(const TypeSpec& expected, + const TypeSpec& actual, + const std::string& error_source_name, + bool print_on_error, + bool throw_on_error) const { bool success = true; // first, typecheck the base types: if (!typecheck_base_types(expected.base_type(), actual.base_type())) { @@ -1033,7 +1037,7 @@ bool TypeSystem::typecheck(const TypeSpec& expected, for (size_t i = 0; i < expected.m_arguments.size(); i++) { // don't print/throw because the error would be confusing. Better to fail only the // outer most check and print a single error message. - if (!typecheck(expected.m_arguments[i], actual.m_arguments[i], "", false, false)) { + if (!tc(expected.m_arguments[i], actual.m_arguments[i])) { success = false; break; } @@ -1266,17 +1270,63 @@ void TypeSystem::add_field_to_bitfield(BitFieldType* type, type->m_fields.push_back(field); } -std::string TypeSystem::generate_deftype(const Type* type) const { +/*! + * Generate the part of a deftype for the flag asserts and methods. + * Doesn't include the final close paren of the deftype + * This should work for both structure/bitfield definitions. + */ +std::string TypeSystem::generate_deftype_footer(const Type* type) const { std::string result; + auto method_count = get_next_method_id(type); + result.append(fmt::format(" :method-count-assert {}\n", get_next_method_id(type))); + result.append(fmt::format(" :size-assert #x{:x}\n", type->get_size_in_memory())); + TypeFlags flags; + flags.heap_base = 0; + flags.size = type->get_size_in_memory(); + flags.pad = 0; + flags.methods = method_count; - auto st = dynamic_cast(type); - if (!st) { - return fmt::format( - ";; cannot generate deftype for {}, it is not a structure/basic (parent {})\n", - type->get_name(), type->get_parent()); + result.append(fmt::format(" :flag-assert #x{:x}\n ", flags.flag)); + + std::string methods_string; + auto new_info = type->get_new_method_defined_for_type(); + if (new_info) { + methods_string.append("(new ("); + for (size_t i = 0; i < new_info->type.arg_count() - 1; i++) { + methods_string.append(new_info->type.get_arg(i).print()); + if (i != new_info->type.arg_count() - 2) { + methods_string.push_back(' '); + } + } + methods_string.append(fmt::format( + ") {} {})\n ", new_info->type.get_arg(new_info->type.arg_count() - 1).print(), 0)); } - result += fmt::format("(deftype {} ({})\n (", type->get_name(), type->get_parent()); + for (auto& info : type->get_methods_defined_for_type()) { + methods_string.append(fmt::format("({} (", info.name)); + for (size_t i = 0; i < info.type.arg_count() - 1; i++) { + methods_string.append(info.type.get_arg(i).print()); + if (i != info.type.arg_count() - 2) { + methods_string.push_back(' '); + } + } + methods_string.append(fmt::format( + ") {} {})\n ", info.type.get_arg(info.type.arg_count() - 1).print(), info.id)); + } + + if (!methods_string.empty()) { + result.append("(:methods\n "); + result.append(methods_string); + result.append(")\n "); + } + + result.append(")\n"); + return result; +} + +std::string TypeSystem::generate_deftype_for_structure(const StructureType* st) const { + std::string result; + result += fmt::format("(deftype {} ({})\n (", st->get_name(), st->get_parent()); int longest_field_name = 0; int longest_type_name = 0; @@ -1342,52 +1392,56 @@ std::string TypeSystem::generate_deftype(const Type* type) const { result.append(std::to_string(field.offset())); result.append(")\n "); } - result.append(")\n"); - - auto method_count = get_next_method_id(type); - result.append(fmt::format(" :method-count-assert {}\n", get_next_method_id(type))); - result.append(fmt::format(" :size-assert #x{:x}\n", type->get_size_in_memory())); - TypeFlags flags; - flags.heap_base = 0; - flags.size = type->get_size_in_memory(); - flags.pad = 0; - flags.methods = method_count; - - result.append(fmt::format(" :flag-assert #x{:x}\n ", flags.flag)); - - std::string methods_string; - auto new_info = type->get_new_method_defined_for_type(); - if (new_info) { - methods_string.append("(new ("); - for (size_t i = 0; i < new_info->type.arg_count() - 1; i++) { - methods_string.append(new_info->type.get_arg(i).print()); - if (i != new_info->type.arg_count() - 2) { - methods_string.push_back(' '); - } - } - methods_string.append(fmt::format( - ") {} {})\n ", new_info->type.get_arg(new_info->type.arg_count() - 1).print(), 0)); - } - - for (auto& info : type->get_methods_defined_for_type()) { - methods_string.append(fmt::format("({} (", info.name)); - for (size_t i = 0; i < info.type.arg_count() - 1; i++) { - methods_string.append(info.type.get_arg(i).print()); - if (i != info.type.arg_count() - 2) { - methods_string.push_back(' '); - } - } - methods_string.append(fmt::format( - ") {} {})\n ", info.type.get_arg(info.type.arg_count() - 1).print(), info.id)); - } - - if (!methods_string.empty()) { - result.append("(:methods\n "); - result.append(methods_string); - result.append(")\n "); - } result.append(")\n"); + result.append(generate_deftype_footer(st)); return result; +} + +std::string TypeSystem::generate_deftype_for_bitfield(const BitFieldType* type) const { + std::string result; + result += fmt::format("(deftype {} ({})\n (", type->get_name(), type->get_parent()); + + int longest_field_name = 0; + int longest_type_name = 0; + + for (const auto& field : type->fields()) { + longest_field_name = std::max(longest_field_name, int(field.name().size())); + longest_type_name = std::max(longest_type_name, int(field.type().print().size())); + } + + for (const auto& field : type->fields()) { + result += "("; + result += field.name(); + result.append(1 + (longest_field_name - int(field.name().size())), ' '); + result += field.type().print(); + result.append(1 + (longest_type_name - int(field.type().print().size())), ' '); + + result.append(fmt::format(":offset {:3d} :size {:3d}", field.offset(), field.size())); + result.append(")\n "); + } + + result.append(")\n"); + result.append(generate_deftype_footer(type)); + + return result; +} + +std::string TypeSystem::generate_deftype(const Type* type) const { + std::string result; + + auto st = dynamic_cast(type); + if (st) { + return generate_deftype_for_structure(st); + } + + auto bf = dynamic_cast(type); + if (bf) { + return generate_deftype_for_bitfield(bf); + } + + return fmt::format( + ";; cannot generate deftype for {}, it is not a structure, basic, or bitfield (parent {})\n", + type->get_name(), type->get_parent()); } \ No newline at end of file diff --git a/common/type_system/TypeSystem.h b/common/type_system/TypeSystem.h index ea04e285b8..8fa8491ce1 100644 --- a/common/type_system/TypeSystem.h +++ b/common/type_system/TypeSystem.h @@ -133,6 +133,9 @@ class TypeSystem { void assert_method_id(const std::string& type_name, const std::string& method_name, int id); std::string generate_deftype(const Type* type) const; + std::string generate_deftype_for_structure(const StructureType* type) const; + std::string generate_deftype_for_bitfield(const BitFieldType* type) const; + std::string generate_deftype_footer(const Type* type) const; FieldLookupInfo lookup_field_info(const std::string& type_name, const std::string& field_name) const; @@ -151,11 +154,12 @@ class TypeSystem { void add_builtin_types(); std::string print_all_type_information() const; - bool typecheck(const TypeSpec& expected, - const TypeSpec& actual, - const std::string& error_source_name = "", - bool print_on_error = true, - bool throw_on_error = true) const; + bool typecheck_and_throw(const TypeSpec& expected, + const TypeSpec& actual, + const std::string& error_source_name = "", + bool print_on_error = true, + bool throw_on_error = true) const; + bool tc(const TypeSpec& expected, const TypeSpec& actual) const; std::vector get_path_up_tree(const std::string& type) const; int get_next_method_id(const Type* type) const; diff --git a/common/type_system/deftype.cpp b/common/type_system/deftype.cpp index 5e972d1b2c..af86ecd251 100644 --- a/common/type_system/deftype.cpp +++ b/common/type_system/deftype.cpp @@ -53,7 +53,7 @@ std::string deftype_parent_list(const goos::Object& list) { } bool is_type(const std::string& expected, const TypeSpec& actual, const TypeSystem* ts) { - return ts->typecheck(ts->make_typespec(expected), actual, "", false, false); + return ts->tc(ts->make_typespec(expected), actual); } template diff --git a/decompiler/IR2/AtomicOp.cpp b/decompiler/IR2/AtomicOp.cpp index e1bbe6fef9..462c10f6b4 100644 --- a/decompiler/IR2/AtomicOp.cpp +++ b/decompiler/IR2/AtomicOp.cpp @@ -134,7 +134,11 @@ goos::Object SimpleAtom::to_form(const std::vector& labels, con case Kind::INTEGER_CONSTANT: return goos::Object::make_integer(m_int); case Kind::SYMBOL_PTR: - return pretty_print::to_symbol(fmt::format("'{}", m_string)); + if (m_string == "#t") { + return pretty_print::to_symbol("#t"); + } else { + return pretty_print::to_symbol(fmt::format("'{}", m_string)); + } case Kind::SYMBOL_VAL: return pretty_print::to_symbol(m_string); case Kind::EMPTY_LIST: diff --git a/decompiler/IR2/AtomicOp.h b/decompiler/IR2/AtomicOp.h index 389d96c597..825784ad67 100644 --- a/decompiler/IR2/AtomicOp.h +++ b/decompiler/IR2/AtomicOp.h @@ -152,6 +152,8 @@ class SimpleAtom { bool is_sym_val() const { return m_kind == Kind::SYMBOL_VAL; }; bool is_empty_list() const { return m_kind == Kind::EMPTY_LIST; }; bool is_static_addr() const { return m_kind == Kind::STATIC_ADDRESS; }; + Kind get_kind() const { return m_kind; } + bool operator==(const SimpleAtom& other) const; bool operator!=(const SimpleAtom& other) const { return !((*this) == other); } void get_regs(std::vector* out) const; diff --git a/decompiler/IR2/AtomicOpForm.cpp b/decompiler/IR2/AtomicOpForm.cpp index 4b93bb2214..c5daae7703 100644 --- a/decompiler/IR2/AtomicOpForm.cpp +++ b/decompiler/IR2/AtomicOpForm.cpp @@ -106,8 +106,76 @@ FormElement* SetVarConditionOp::get_as_form(FormPool& pool, const Env& env) cons FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const { if (env.has_type_analysis()) { if (m_addr.is_identity() && m_addr.get_arg(0).is_sym_val()) { - return pool.alloc_element(m_addr.get_arg(0).get_str(), - m_value.as_expr(), m_my_idx); + // we are storing a value in a global symbol. This is something like sw rx, offset(s7) + // so the source can only be a variable, r0 (integer 0), or false (s7) + // we want to know both: what cast (if any) do we need for a set!, and what cast (if any) + // do we need for a define. + + auto symbol_type = env.dts->lookup_symbol_type(m_addr.get_arg(0).get_str()); + auto symbol_type_info = env.dts->ts.lookup_type(symbol_type); + + switch (m_value.get_kind()) { + case SimpleAtom::Kind::VARIABLE: { + auto src_type = env.get_types_before_op(m_my_idx).get(m_value.var().reg()).typespec(); + std::optional cast_for_set, cast_for_define; + + if (src_type != symbol_type) { + // the define will need a cast to the exactly right type. + cast_for_define = symbol_type; + } + + if (!env.dts->ts.tc(symbol_type, src_type)) { + // we fail the typecheck for a normal set!, so add a cast. + cast_for_set = symbol_type; + } + + return pool.alloc_element(m_addr.get_arg(0).get_str(), + m_value.as_expr(), cast_for_set, + cast_for_define, m_my_idx); + } break; + case SimpleAtom::Kind::INTEGER_CONSTANT: { + std::optional cast_for_set, cast_for_define; + bool sym_int_or_uint = env.dts->ts.tc(TypeSpec("integer"), symbol_type); + bool sym_uint = env.dts->ts.tc(TypeSpec("uinteger"), symbol_type); + bool sym_int = sym_int_or_uint && !sym_uint; + + if (TypeSpec("int") != symbol_type) { + // the define will need a cast to the exactly right type. + cast_for_define = symbol_type; + } + + if (sym_int) { + // do nothing for set. + } else { + // for uint or other + cast_for_set = symbol_type; + } + + return pool.alloc_element(m_addr.get_arg(0).get_str(), + m_value.as_expr(), cast_for_set, + cast_for_define, m_my_idx); + } break; + + case SimpleAtom::Kind::SYMBOL_PTR: + case SimpleAtom::Kind::SYMBOL_VAL: { + assert(m_value.get_str() == "#f"); + std::optional cast_for_set, cast_for_define; + if (symbol_type != TypeSpec("symbol")) { + cast_for_define = symbol_type; + // explicitly cast if we're not using a reference type, including pointers. + // otherwise, we allow setting references to #f. + if (!symbol_type_info->is_reference()) { + cast_for_set = symbol_type; + } + } + return pool.alloc_element(m_addr.get_arg(0).get_str(), + m_value.as_expr(), cast_for_set, + cast_for_define, m_my_idx); + } break; + + default: + assert(false); + } } IR2_RegOffset ro; @@ -362,20 +430,36 @@ FormElement* LoadVarOp::get_as_form(FormPool& pool, const Env& env) const { } } - if (m_src.is_identity() && m_src.get_arg(0).is_label() && - (m_kind == Kind::FLOAT || m_kind == Kind::SIGNED) && m_size == 4) { + if (m_src.is_identity() && m_src.get_arg(0).is_label()) { // try to see if we're loading a constant auto label = env.file->labels.at(m_src.get_arg(0).label()); auto label_name = label.name; auto hint = env.label_types().find(label_name); if (hint != env.label_types().end()) { - if (hint->second.is_const && hint->second.type_name == "float") { - auto word = env.file->words_by_seg.at(label.target_segment).at(label.offset / 4); - assert(word.kind == LinkedWord::PLAIN_DATA); - float value; - memcpy(&value, &word.data, 4); - auto float_elt = pool.alloc_single_element_form(nullptr, value); - return pool.alloc_element(m_dst, float_elt, true); + if (hint->second.is_const) { + if ((m_kind == Kind::FLOAT || m_kind == Kind::SIGNED) && m_size == 4 && + hint->second.type_name == "float") { + assert((label.offset % 4) == 0); + auto word = env.file->words_by_seg.at(label.target_segment).at(label.offset / 4); + assert(word.kind == LinkedWord::PLAIN_DATA); + float value; + memcpy(&value, &word.data, 4); + auto float_elt = pool.alloc_single_element_form(nullptr, value); + return pool.alloc_element(m_dst, float_elt, true); + } else if (hint->second.type_name == "uint64" && m_kind != Kind::FLOAT && m_size == 8) { + assert((label.offset % 8) == 0); + auto word0 = env.file->words_by_seg.at(label.target_segment).at(label.offset / 4); + auto word1 = env.file->words_by_seg.at(label.target_segment).at(1 + (label.offset / 4)); + assert(word0.kind == LinkedWord::PLAIN_DATA); + assert(word1.kind == LinkedWord::PLAIN_DATA); + u64 value; + + memcpy(&value, &word0.data, 4); + memcpy(((u8*)&value) + 4, &word1.data, 4); + auto val_elt = pool.alloc_single_element_form( + nullptr, fmt::format("#x{:x}", value)); + return pool.alloc_element(m_dst, val_elt, true); + } } } } diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index 42420532ff..60f8bd154e 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -8,7 +8,7 @@ namespace decompiler { namespace { bool tc(const DecompilerTypeSystem& dts, const TypeSpec& expected, const TP_Type& actual) { - return dts.ts.typecheck(expected, actual.typespec(), "", false, false); + return dts.ts.tc(expected, actual.typespec()); } bool is_int_or_uint(const DecompilerTypeSystem& dts, const TP_Type& type) { diff --git a/decompiler/IR2/Form.cpp b/decompiler/IR2/Form.cpp index 2953611912..6e9fd12466 100644 --- a/decompiler/IR2/Form.cpp +++ b/decompiler/IR2/Form.cpp @@ -322,11 +322,26 @@ bool SetVarElement::active() const { } } -StoreInSymbolElement::StoreInSymbolElement(std::string sym_name, SimpleExpression value, int my_idx) - : m_sym_name(std::move(sym_name)), m_value(std::move(value)), m_my_idx(my_idx) {} +StoreInSymbolElement::StoreInSymbolElement(std::string sym_name, + SimpleExpression value, + std::optional cast_for_set, + std::optional cast_for_define, + int my_idx) + : m_sym_name(std::move(sym_name)), + m_value(std::move(value)), + m_cast_for_set(std::move(cast_for_set)), + m_cast_for_define(std::move(cast_for_define)), + m_my_idx(my_idx) {} goos::Object StoreInSymbolElement::to_form_internal(const Env& env) const { - return pretty_print::build_list("set!", m_sym_name, m_value.to_form(env.file->labels, env)); + if (m_cast_for_set) { + return pretty_print::build_list( + "set!", m_sym_name, + pretty_print::build_list(fmt::format("the-as {}", m_cast_for_set->print()), + m_value.to_form(env.file->labels, env))); + } else { + return pretty_print::build_list("set!", m_sym_name, m_value.to_form(env.file->labels, env)); + } } void StoreInSymbolElement::apply(const std::function& f) { @@ -370,15 +385,42 @@ void StoreInPairElement::get_modified_regs(RegSet&) const {} // SetFormFormElement ///////////////////////////// -SetFormFormElement::SetFormFormElement(Form* dst, Form* src) : m_dst(dst), m_src(src) { +SetFormFormElement::SetFormFormElement(Form* dst, + Form* src, + std::optional cast_for_set, + std::optional cast_for_define) + : m_dst(dst), + m_src(src), + m_cast_for_set(std::move(cast_for_set)), + m_cast_for_define(std::move(cast_for_define)) { m_dst->parent_element = this; m_src->parent_element = this; } goos::Object SetFormFormElement::to_form_internal(const Env& env) const { - std::vector forms = {pretty_print::to_symbol("set!"), m_dst->to_form(env), - m_src->to_form(env)}; - return pretty_print::build_list(forms); + if (m_cast_for_set) { + return pretty_print::build_list( + fmt::format("set!"), m_dst->to_form(env), + pretty_print::build_list(fmt::format("the-as {}", m_cast_for_set->print()), + m_src->to_form(env))); + } else { + std::vector forms = {pretty_print::to_symbol("set!"), m_dst->to_form(env), + m_src->to_form(env)}; + return pretty_print::build_list(forms); + } +} + +goos::Object SetFormFormElement::to_form_for_define(const Env& env) const { + if (m_cast_for_define) { + return pretty_print::build_list( + fmt::format("define"), m_dst->to_form(env), + pretty_print::build_list(fmt::format("the-as {}", m_cast_for_define->print()), + m_src->to_form(env))); + } else { + std::vector forms = {pretty_print::to_symbol("define"), m_dst->to_form(env), + m_src->to_form(env)}; + return pretty_print::build_list(forms); + } } void SetFormFormElement::apply(const std::function& f) { diff --git a/decompiler/IR2/Form.h b/decompiler/IR2/Form.h index adcc05265a..0526f3e291 100644 --- a/decompiler/IR2/Form.h +++ b/decompiler/IR2/Form.h @@ -277,7 +277,11 @@ class SetVarElement : public FormElement { class StoreInSymbolElement : public FormElement { public: - StoreInSymbolElement(std::string sym_name, SimpleExpression value, int my_idx); + StoreInSymbolElement(std::string sym_name, + SimpleExpression value, + std::optional cast_for_set, + std::optional cast_for_define, + int my_idx); goos::Object to_form_internal(const Env& env) const override; void apply(const std::function& f) override; void apply_form(const std::function& f) override; @@ -288,6 +292,8 @@ class StoreInSymbolElement : public FormElement { private: std::string m_sym_name; SimpleExpression m_value; + std::optional m_cast_for_set; + std::optional m_cast_for_define; int m_my_idx = -1; }; @@ -315,8 +321,12 @@ class StoreInPairElement : public FormElement { */ class SetFormFormElement : public FormElement { public: - SetFormFormElement(Form* dst, Form* src); + SetFormFormElement(Form* dst, + Form* src, + std::optional cast_for_set = {}, + std::optional cast_for_define = {}); goos::Object to_form_internal(const Env& env) const override; + goos::Object to_form_for_define(const Env& env) const; void apply(const std::function& f) override; void apply_form(const std::function& f) override; bool is_sequence_point() const override; @@ -333,6 +343,7 @@ class SetFormFormElement : public FormElement { int m_real_push_count = 0; Form* m_dst = nullptr; Form* m_src = nullptr; + std::optional m_cast_for_set, m_cast_for_define; }; /*! diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index df51515cf1..229b72dfab 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -1078,7 +1078,7 @@ void StoreInSymbolElement::push_to_stack(const Env& env, FormPool& pool, FormSta auto val = pool.alloc_single_element_form(nullptr, m_value, m_my_idx); val->update_children_from_stack(env, pool, stack, true); - auto elt = pool.alloc_element(sym, val); + auto elt = pool.alloc_element(sym, val, m_cast_for_set, m_cast_for_define); elt->mark_popped(); stack.push_form_element(elt, true); } @@ -1263,7 +1263,7 @@ void FunctionCallElement::update_from_stack(const Env& env, if (env.has_type_analysis() && function_type.arg_count() == nargs + 1) { auto actual_arg_type = env.get_types_before_op(var.idx()).get(var.reg()).typespec(); auto desired_arg_type = function_type.get_arg(arg_id); - if (!env.dts->ts.typecheck(desired_arg_type, actual_arg_type, "", false, false)) { + if (!env.dts->ts.tc(desired_arg_type, actual_arg_type)) { arg_forms.push_back( pool.alloc_single_element_form(nullptr, desired_arg_type, val)); } else { @@ -1387,7 +1387,7 @@ void FunctionCallElement::update_from_stack(const Env& env, for (size_t i = 0; i < 3; i++) { auto& var = all_pop_vars.at(i + 1); // 0 is the function itself. auto arg_type = env.get_types_before_op(var.idx()).get(var.reg()).typespec(); - if (!env.dts->ts.typecheck(expected_arg_types.at(i), arg_type, "", false, false)) { + if (!env.dts->ts.tc(expected_arg_types.at(i), arg_type)) { new_args.at(i) = pool.alloc_single_element_form( nullptr, expected_arg_types.at(i), new_args.at(i)); } diff --git a/decompiler/analysis/expression_build.cpp b/decompiler/analysis/expression_build.cpp index 450019aecc..04712b1970 100644 --- a/decompiler/analysis/expression_build.cpp +++ b/decompiler/analysis/expression_build.cpp @@ -73,7 +73,7 @@ bool convert_to_expressions(Form* top_level_form, new_entries = rewrite_to_get_var(stack, pool, return_var, f.ir2.env); auto reg_return_type = f.ir2.env.get_types_after_op(f.ir2.atomic_ops->ops.size() - 1).get(return_var.reg()); - if (!dts.ts.typecheck(f.type.last_arg(), reg_return_type.typespec(), "", false, false)) { + if (!dts.ts.tc(f.type.last_arg(), reg_return_type.typespec())) { // we need to cast the final value. auto to_cast = new_entries.back(); new_entries.pop_back(); diff --git a/decompiler/analysis/final_output.cpp b/decompiler/analysis/final_output.cpp index fa78bb4139..c5718a13f5 100644 --- a/decompiler/analysis/final_output.cpp +++ b/decompiler/analysis/final_output.cpp @@ -202,6 +202,9 @@ std::string write_from_top_level(const Function& top_level, auto defun_debug_matcher = Matcher::if_with_else(debug_seg_matcher, debug_def_matcher, non_debug_def_matcher); + // (set! sym-val ) + auto define_symbol_matcher = Matcher::set(Matcher::any_symbol(0), Matcher::any(1)); + for (auto& x : top_form->elts()) { bool something_matched = false; Form f; @@ -275,6 +278,21 @@ std::string write_from_top_level(const Function& top_level, } } + if (!something_matched) { + auto define_match_result = match(define_symbol_matcher, &f); + if (define_match_result.matched) { + something_matched = true; + auto sym_name = define_match_result.maps.strings.at(0); + auto symbol_type = dts.lookup_symbol_type(sym_name); + result += + fmt::format(";; definition for symbol {}, type {}\n", sym_name, symbol_type.print()); + auto setset = dynamic_cast(f.try_as_single_element()); + assert(setset); + result += pretty_print::to_string(setset->to_form_for_define(env)); + result += "\n\n"; + } + } + if (!something_matched) { result += ";; failed to figure out what this is:\n"; result += pretty_print::to_string(x->to_form(env)); diff --git a/decompiler/config/jak1_ntsc_black_label.jsonc b/decompiler/config/jak1_ntsc_black_label.jsonc index 4ef96775d5..6d60967c26 100644 --- a/decompiler/config/jak1_ntsc_black_label.jsonc +++ b/decompiler/config/jak1_ntsc_black_label.jsonc @@ -93,13 +93,7 @@ "joint-anim-matrix", "part-tracker"], - "no_type_analysis_functions_by_name":[ - "breakpoint-range-set!", // messing with COP0 registers - "(method 0 catch-frame)", // kernel asm - "throw-dispatch", // kernel asm - "reset-and-call", // stack manipulation - "(method 10 cpu-thread)" // loading saved regs off of the stack. - ], + "no_type_analysis_functions_by_name":[], "asm_functions_by_name":[ diff --git a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc index 7439128384..bef767c9b1 100644 --- a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc @@ -1,6 +1,7 @@ { "gcommon":[ - ["L345", "float", true] + ["L345", "float", true], + ["L346", "uint64", true] ], "math":[ diff --git a/decompiler/util/DecompilerTypeSystem.cpp b/decompiler/util/DecompilerTypeSystem.cpp index 8865e0a7f3..7be4bc9393 100644 --- a/decompiler/util/DecompilerTypeSystem.cpp +++ b/decompiler/util/DecompilerTypeSystem.cpp @@ -156,7 +156,7 @@ void DecompilerTypeSystem::add_symbol(const std::string& name, const TypeSpec& t if (skv == symbol_types.end() || skv->second == type_spec) { symbol_types[name] = type_spec; } else { - if (ts.typecheck(type_spec, skv->second, "", false, false)) { + if (ts.tc(type_spec, skv->second)) { } else { lg::warn("Attempting to redefine type of symbol {} from {} to {}\n", name, skv->second.print(), type_spec.print()); @@ -384,4 +384,14 @@ int DecompilerTypeSystem::get_format_arg_count(const TP_Type& type) const { return type.get_format_string_arg_count(); } } + +TypeSpec DecompilerTypeSystem::lookup_symbol_type(const std::string& name) const { + auto kv = symbol_types.find(name); + if (kv == symbol_types.end()) { + throw std::runtime_error( + fmt::format("Decompiler type system did not know the type of symbol {}. Add it!", name)); + } else { + return kv->second; + } +} } // namespace decompiler \ No newline at end of file diff --git a/decompiler/util/DecompilerTypeSystem.h b/decompiler/util/DecompilerTypeSystem.h index e098e296da..f82e029753 100644 --- a/decompiler/util/DecompilerTypeSystem.h +++ b/decompiler/util/DecompilerTypeSystem.h @@ -42,6 +42,8 @@ class DecompilerTypeSystem { bool tp_lca(TypeState* combined, const TypeState& add); int get_format_arg_count(const std::string& str) const; int get_format_arg_count(const TP_Type& type) const; + TypeSpec lookup_symbol_type(const std::string& name) const; + struct { bool locked = false; bool allow_pair; diff --git a/decompiler/util/data_decompile.cpp b/decompiler/util/data_decompile.cpp index 2e003e328e..fcdd002266 100644 --- a/decompiler/util/data_decompile.cpp +++ b/decompiler/util/data_decompile.cpp @@ -138,11 +138,11 @@ goos::Object decompile_at_label(const TypeSpec& type, return decompile_string_at_label(label, words); } - if (ts.typecheck(TypeSpec("array"), type, "", false, false)) { + if (ts.tc(TypeSpec("array"), type)) { return decompile_boxed_array(label, labels, words, ts); } - if (ts.typecheck(TypeSpec("structure"), type, "", false, false)) { + if (ts.tc(TypeSpec("structure"), type)) { return decompile_structure(type, label, labels, words, ts); } @@ -321,7 +321,7 @@ goos::Object decompile_structure(const TypeSpec& type, if (word.symbol_name != actual_type.base_type()) { // we can specify a more specific type. auto got_type = TypeSpec(word.symbol_name); - if (ts.typecheck(actual_type, got_type, "", false, false)) { + if (ts.tc(actual_type, got_type)) { lg::info("For type {}, got more specific type {}\n", actual_type.print(), got_type.print()); actual_type = got_type; @@ -530,12 +530,12 @@ goos::Object decompile_value(const TypeSpec& type, const std::vector& bytes, const TypeSystem& ts) { // try as common integer types: - if (ts.typecheck(TypeSpec("uint32"), type, "", false, false)) { + if (ts.tc(TypeSpec("uint32"), type)) { assert(bytes.size() == 4); u32 value; memcpy(&value, bytes.data(), 4); return pretty_print::to_symbol(fmt::format("#x{:x}", u64(value))); - } else if (ts.typecheck(TypeSpec("int32"), type, "", false, false)) { + } else if (ts.tc(TypeSpec("int32"), type)) { assert(bytes.size() == 4); s32 value; memcpy(&value, bytes.data(), 4); @@ -544,7 +544,7 @@ goos::Object decompile_value(const TypeSpec& type, } else { return pretty_print::to_symbol(fmt::format("{}", value)); } - } else if (ts.typecheck(TypeSpec("int8"), type, "", false, false)) { + } else if (ts.tc(TypeSpec("int8"), type)) { assert(bytes.size() == 1); s8 value; memcpy(&value, bytes.data(), 1); @@ -553,17 +553,17 @@ goos::Object decompile_value(const TypeSpec& type, } else { return pretty_print::to_symbol(fmt::format("{}", value)); } - } else if (ts.typecheck(TypeSpec("uint64"), type, "", false, false)) { + } else if (ts.tc(TypeSpec("uint64"), type)) { assert(bytes.size() == 8); u64 value; memcpy(&value, bytes.data(), 8); return pretty_print::to_symbol(fmt::format("#x{:x}", value)); - } else if (ts.typecheck(TypeSpec("float"), type, "", false, false)) { + } else if (ts.tc(TypeSpec("float"), type)) { assert(bytes.size() == 4); float value; memcpy(&value, bytes.data(), 4); return pretty_print::float_representation(value); - } else if (ts.typecheck(TypeSpec("uint8"), type, "", false, false)) { + } else if (ts.tc(TypeSpec("uint8"), type)) { assert(bytes.size() == 1); u8 value; memcpy(&value, bytes.data(), 1); diff --git a/doc/goal_doc.md b/doc/goal_doc.md index fe74390fa9..84438a27c0 100644 --- a/doc/goal_doc.md +++ b/doc/goal_doc.md @@ -618,6 +618,13 @@ This form is reserved by the compiler. Internally all forms in a file are groupe # Compiler Forms - Compiler Commands These forms are used to control the GOAL compiler, and are usually entered at the GOAL REPL, or as part of a macro that's executed at the GOAL REPL. These shouldn't be used in GOAL source code. +## `reload` +Reload the GOAL compiler +```lisp +(reload) +``` +Disconnect from the target and reset all compiler state. This is equivalent to exiting the compiler and opening it again. + ## `seval` Execute GOOS code. ```lisp diff --git a/goalc/compiler/Compiler.cpp b/goalc/compiler/Compiler.cpp index 80ad8838f8..0967ba1b15 100644 --- a/goalc/compiler/Compiler.cpp +++ b/goalc/compiler/Compiler.cpp @@ -20,8 +20,8 @@ Compiler::Compiler() : m_debugger(&m_listener) { compile_object_file("goal-lib", library_code, false); } -void Compiler::execute_repl() { - while (!m_want_exit) { +ReplStatus Compiler::execute_repl() { + while (!m_want_exit && !m_want_reload) { try { // 1). get a line from the user (READ) std::string prompt = "g"; @@ -69,6 +69,16 @@ void Compiler::execute_repl() { } m_listener.disconnect(); + + if (m_want_exit) { + return ReplStatus::WANT_EXIT; + } + + if (m_want_reload) { + return ReplStatus::WANT_RELOAD; + } + + return ReplStatus::OK; } FileEnv* Compiler::compile_object_file(const std::string& name, @@ -329,8 +339,9 @@ void Compiler::typecheck(const goos::Object& form, const TypeSpec& actual, const std::string& error_message) { (void)form; - if (!m_ts.typecheck(expected, actual, error_message, true, false)) { - throw_compiler_error(form, "Typecheck failed"); + if (!m_ts.typecheck_and_throw(expected, actual, error_message, false, false)) { + throw_compiler_error(form, "Typecheck failed. For {}, got a \"{}\" when expecting a \"{}\"", + error_message, actual.print(), expected.print()); } } @@ -342,7 +353,7 @@ void Compiler::typecheck_reg_type_allow_false(const goos::Object& form, const TypeSpec& expected, const Val* actual, const std::string& error_message) { - if (!m_ts.typecheck(m_ts.make_typespec("number"), expected, "", false, false)) { + if (!m_ts.typecheck_and_throw(m_ts.make_typespec("number"), expected, "", false, false)) { auto as_sym_val = dynamic_cast(actual); if (as_sym_val && as_sym_val->name() == "#f") { return; diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index 9f1581ea26..e5162be3b2 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -20,10 +20,12 @@ enum MathMode { MATH_INT, MATH_BINT, MATH_FLOAT, MATH_INVALID }; +enum class ReplStatus { OK, WANT_EXIT, WANT_RELOAD }; + class Compiler { public: Compiler(); - void execute_repl(); + ReplStatus execute_repl(); goos::Interpreter& get_goos() { return m_goos; } FileEnv* compile_object_file(const std::string& name, goos::Object code, bool allow_emit); std::unique_ptr compile_top_level_function(const std::string& name, @@ -187,6 +189,7 @@ class Compiler { std::unique_ptr m_global_env = nullptr; std::unique_ptr m_none = nullptr; bool m_want_exit = false; + bool m_want_reload = false; listener::Listener m_listener; Debugger m_debugger; goos::Interpreter m_goos; @@ -423,6 +426,7 @@ class Compiler { Val* compile_set_config(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_in_package(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_build_dgo(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_reload(const goos::Object& form, const goos::Object& rest, Env* env); // ControlFlow Condition compile_condition(const goos::Object& condition, Env* env, bool invert); diff --git a/goalc/compiler/Util.cpp b/goalc/compiler/Util.cpp index a2a6a3f0e7..2be280f1ee 100644 --- a/goalc/compiler/Util.cpp +++ b/goalc/compiler/Util.cpp @@ -179,11 +179,11 @@ bool Compiler::is_none(Val* in) { } bool Compiler::is_basic(const TypeSpec& ts) { - return m_ts.typecheck(m_ts.make_typespec("basic"), ts, "", false, false); + return m_ts.tc(m_ts.make_typespec("basic"), ts); } bool Compiler::is_structure(const TypeSpec& ts) { - return m_ts.typecheck(m_ts.make_typespec("structure"), ts, "", false, false); + return m_ts.tc(m_ts.make_typespec("structure"), ts); } bool Compiler::is_bitfield(const TypeSpec& ts) { @@ -191,7 +191,7 @@ bool Compiler::is_bitfield(const TypeSpec& ts) { } bool Compiler::is_pair(const TypeSpec& ts) { - return m_ts.typecheck(m_ts.make_typespec("pair"), ts, "", false, false); + return m_ts.tc(m_ts.make_typespec("pair"), ts); } bool Compiler::try_getting_constant_integer(const goos::Object& in, int64_t* out, Env* env) { diff --git a/goalc/compiler/compilation/Atoms.cpp b/goalc/compiler/compilation/Atoms.cpp index 9177807b17..edd5963f6d 100644 --- a/goalc/compiler/compilation/Atoms.cpp +++ b/goalc/compiler/compilation/Atoms.cpp @@ -113,6 +113,7 @@ static const std::unordered_map< {"reset-target", &Compiler::compile_reset_target}, {":status", &Compiler::compile_poke}, {"in-package", &Compiler::compile_in_package}, + {"reload", &Compiler::compile_reload}, // CONDITIONAL COMPILATION {"#cond", &Compiler::compile_gscond}, @@ -432,7 +433,7 @@ Val* Compiler::compile_pointer_add(const goos::Object& form, const goos::Object& bool ok_type = false; for (auto& type : {"pointer", "structure", "inline-array"}) { - if (m_ts.typecheck(m_ts.make_typespec(type), first->type(), "", false, false)) { + if (m_ts.tc(m_ts.make_typespec(type), first->type())) { ok_type = true; break; } diff --git a/goalc/compiler/compilation/CompilerControl.cpp b/goalc/compiler/compilation/CompilerControl.cpp index 606a240345..270b462b2b 100644 --- a/goalc/compiler/compilation/CompilerControl.cpp +++ b/goalc/compiler/compilation/CompilerControl.cpp @@ -383,3 +383,11 @@ Val* Compiler::compile_build_dgo(const goos::Object& form, const goos::Object& r return get_none(); } + +Val* Compiler::compile_reload(const goos::Object& form, const goos::Object& rest, Env* env) { + (void)env; + auto args = get_va(form, rest); + va_check(form, args, {}, {}); + m_want_reload = true; + return get_none(); +} diff --git a/goalc/compiler/compilation/Math.cpp b/goalc/compiler/compilation/Math.cpp index c4c023e6c3..ef4768ae70 100644 --- a/goalc/compiler/compilation/Math.cpp +++ b/goalc/compiler/compilation/Math.cpp @@ -1,15 +1,15 @@ #include "goalc/compiler/Compiler.h" MathMode Compiler::get_math_mode(const TypeSpec& ts) { - if (m_ts.typecheck(m_ts.make_typespec("binteger"), ts, "", false, false)) { + if (m_ts.tc(m_ts.make_typespec("binteger"), ts)) { return MATH_BINT; } - if (m_ts.typecheck(m_ts.make_typespec("integer"), ts, "", false, false)) { + if (m_ts.tc(m_ts.make_typespec("integer"), ts)) { return MATH_INT; } - if (m_ts.typecheck(m_ts.make_typespec("float"), ts, "", false, false)) { + if (m_ts.tc(m_ts.make_typespec("float"), ts)) { return MATH_FLOAT; } @@ -17,25 +17,23 @@ MathMode Compiler::get_math_mode(const TypeSpec& ts) { } bool Compiler::is_number(const TypeSpec& ts) { - return m_ts.typecheck(m_ts.make_typespec("number"), ts, "", false, false); + return m_ts.tc(m_ts.make_typespec("number"), ts); } bool Compiler::is_float(const TypeSpec& ts) { - return m_ts.typecheck(m_ts.make_typespec("float"), ts, "", false, false); + return m_ts.tc(m_ts.make_typespec("float"), ts); } bool Compiler::is_integer(const TypeSpec& ts) { - return m_ts.typecheck(m_ts.make_typespec("integer"), ts, "", false, false) && - !m_ts.typecheck(m_ts.make_typespec("binteger"), ts, "", false, false); + return m_ts.tc(m_ts.make_typespec("integer"), ts) && !m_ts.tc(m_ts.make_typespec("binteger"), ts); } bool Compiler::is_binteger(const TypeSpec& ts) { - return m_ts.typecheck(m_ts.make_typespec("binteger"), ts, "", false, false); + return m_ts.tc(m_ts.make_typespec("binteger"), ts); } bool Compiler::is_singed_integer_or_binteger(const TypeSpec& ts) { - return m_ts.typecheck(m_ts.make_typespec("integer"), ts, "", false, false) && - !m_ts.typecheck(m_ts.make_typespec("uinteger"), ts, "", false, false); + return m_ts.tc(m_ts.make_typespec("integer"), ts) && !m_ts.tc(m_ts.make_typespec("uinteger"), ts); } Val* Compiler::number_to_integer(const goos::Object& form, Val* in, Env* env) { diff --git a/goalc/compiler/compilation/Static.cpp b/goalc/compiler/compilation/Static.cpp index 50434d9ac0..edf94236a2 100644 --- a/goalc/compiler/compilation/Static.cpp +++ b/goalc/compiler/compilation/Static.cpp @@ -126,7 +126,8 @@ void Compiler::compile_static_structure_inline(const goos::Object& form, } } else { // allow more specific types. - m_ts.typecheck(field_info.field.type(), array_content_type, "Array content type"); + // TODO make this better. + m_ts.typecheck_and_throw(field_info.field.type(), array_content_type, "Array content type"); } s64 elt_array_len; diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp index dc8eb5fdb0..4ff942581d 100644 --- a/goalc/compiler/compilation/Type.cpp +++ b/goalc/compiler/compilation/Type.cpp @@ -112,7 +112,7 @@ void Compiler::generate_field_description(const goos::Object& form, const Field& f) { std::string str_template; std::vector format_args = {}; - if (m_ts.typecheck(m_ts.make_typespec("type"), f.type(), "", false, false)) { + if (m_ts.tc(m_ts.make_typespec("type"), f.type())) { // type return; } else if (f.is_array() && !f.is_dynamic()) { @@ -123,17 +123,17 @@ void Compiler::generate_field_description(const goos::Object& form, // Dynamic Field str_template += fmt::format("~T{}[0] @ #x~X~%", f.name()); format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env)); - } else if (m_ts.typecheck(m_ts.make_typespec("basic"), f.type(), "", false, false) || - m_ts.typecheck(m_ts.make_typespec("binteger"), f.type(), "", false, false) || - m_ts.typecheck(m_ts.make_typespec("pair"), f.type(), "", false, false)) { + } else if (m_ts.tc(m_ts.make_typespec("basic"), f.type()) || + m_ts.tc(m_ts.make_typespec("binteger"), f.type()) || + m_ts.tc(m_ts.make_typespec("pair"), f.type())) { // basic, binteger, pair str_template += fmt::format("~T{}: ~A~%", f.name()); format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env)); - } else if (m_ts.typecheck(m_ts.make_typespec("structure"), f.type(), "", false, false)) { + } else if (m_ts.tc(m_ts.make_typespec("structure"), f.type())) { // Structure str_template += fmt::format("~T{}: #<{} @ #x~X>~%", f.name(), f.type().print()); format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env)); - } else if (m_ts.typecheck(m_ts.make_typespec("integer"), f.type(), "", false, false)) { + } else if (m_ts.tc(m_ts.make_typespec("integer"), f.type())) { // Integer if (f.type().print() == "uint128") { str_template += fmt::format("~T{}: ~%", f.name()); @@ -142,11 +142,11 @@ void Compiler::generate_field_description(const goos::Object& form, format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env)); } - } else if (m_ts.typecheck(m_ts.make_typespec("float"), f.type(), "", false, false)) { + } else if (m_ts.tc(m_ts.make_typespec("float"), f.type())) { // Float str_template += fmt::format("~T{}: ~f~%", f.name()); format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env)); - } else if (m_ts.typecheck(m_ts.make_typespec("pointer"), f.type(), "", false, false)) { + } else if (m_ts.tc(m_ts.make_typespec("pointer"), f.type())) { // Pointers str_template += fmt::format("~T{}: #x~X~%", f.name()); format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env)); @@ -626,11 +626,11 @@ Val* Compiler::compile_the(const goos::Object& form, const goos::Object& rest, E auto base = compile_error_guard(args.unnamed.at(1), env); if (is_number(base->type())) { - if (m_ts.typecheck(m_ts.make_typespec("binteger"), desired_ts, "", false, false)) { + if (m_ts.tc(m_ts.make_typespec("binteger"), desired_ts)) { return number_to_binteger(form, base, env); } - if (m_ts.typecheck(m_ts.make_typespec("integer"), desired_ts, "", false, false)) { + if (m_ts.tc(m_ts.make_typespec("integer"), desired_ts)) { auto result = number_to_integer(form, base, env); if (result != base) { result->set_type(desired_ts); @@ -641,7 +641,7 @@ Val* Compiler::compile_the(const goos::Object& form, const goos::Object& rest, E } } - if (m_ts.typecheck(m_ts.make_typespec("float"), desired_ts, "", false, false)) { + if (m_ts.tc(m_ts.make_typespec("float"), desired_ts)) { return number_to_float(form, base, env); } } diff --git a/goalc/main.cpp b/goalc/main.cpp index 40f0d0362e..d9b0c31dfb 100644 --- a/goalc/main.cpp +++ b/goalc/main.cpp @@ -43,7 +43,7 @@ int main(int argc, char** argv) { lg::info("OpenGOAL Compiler {}.{}", versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR); - Compiler compiler; + std::unique_ptr compiler = std::make_unique(); // Welcome message / brief intro for documentation std::string ascii; @@ -65,9 +65,16 @@ int main(int argc, char** argv) { ReplHistory::repl_load_history(); if (argument.empty()) { - compiler.execute_repl(); + ReplStatus status = ReplStatus::WANT_RELOAD; + while (status == ReplStatus::WANT_RELOAD) { + compiler = std::make_unique(); + status = compiler->execute_repl(); + if (status == ReplStatus::WANT_RELOAD) { + fmt::print("Reloading compiler...\n"); + } + } } else { - compiler.run_front_end_on_string(argument); + compiler->run_front_end_on_string(argument); } return 0; diff --git a/test/decompiler/reference/gcommon_REF.gc b/test/decompiler/reference/gcommon_REF.gc index e62d9a3c70..3fa637b57c 100644 --- a/test/decompiler/reference/gcommon_REF.gc +++ b/test/decompiler/reference/gcommon_REF.gc @@ -8,7 +8,7 @@ ;; definition for function 1/ (defun 1/ ((x float)) - (/ 1.000000 x) + (/ 1.0 x) ) ;; definition for function + @@ -92,13 +92,22 @@ (defun false-func () #f) ;; definition for function true-func -(defun true-func () '#t) +(defun true-func () #t) -;; failed to figure out what this is: -(set! format _format) +;; definition for symbol format, type (function _varargs_ object) +(define format _format) ;; definition of type vec4s -;; cannot generate deftype for vec4s, it is not a structure/basic (parent uint128) +(deftype vec4s (uint128) + ((x float :offset 0 :size 32) + (y float :offset 32 :size 32) + (z float :offset 64 :size 32) + (w float :offset 96 :size 32) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) ;; definition for method of type vec4s @@ -128,24 +137,24 @@ ) (.por gp-0 obj r0-0) (set! t9-0 format) - (set! a0-1 '#t) + (set! a0-1 #t) (set! a1-0 "[~8x] ~A~%") (.por a2-0 gp-0 r0-0) (t9-0 a0-1 a1-0 a2-0 'vec4s) (set! t9-1 format) - (set! a0-2 '#t) + (set! a0-2 #t) (set! a1-1 "~Tx: ~f~%") (.sllv a2-1 gp-0 r0-0) (t9-1 a0-2 a1-1 a2-1) - (format '#t "~Ty: ~f~%" (sar gp-0 32)) + (format #t "~Ty: ~f~%" (sar gp-0 32)) (set! t9-3 format) - (set! a0-4 '#t) + (set! a0-4 #t) (set! a1-3 "~Tz: ~f~%") (.pcpyud v1-0 gp-0 r0-0) (.sllv a2-3 v1-0 r0-0) (t9-3 a0-4 a1-3 a2-3) (set! t9-4 format) - (set! a0-5 '#t) + (set! a0-5 #t) (set! a1-4 "~Tw: ~f~%") (.pcpyud v1-1 gp-0 r0-0) (t9-4 a0-5 a1-4 (sar v1-1 32)) @@ -173,7 +182,7 @@ ) (.por gp-0 obj r0-0) (set! t9-0 format) - (set! a0-1 '#t) + (set! a0-1 #t) (set! a1-0 "#") (.sllv a2-0 gp-0 r0-0) (set! a3-0 (sar gp-0 32)) @@ -199,21 +208,21 @@ ;; definition for method of type bfloat (defmethod inspect bfloat ((obj bfloat)) - (format '#t "[~8x] ~A~%" obj (-> obj type)) - (format '#t "~Tdata: ~f~%" (-> obj data)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tdata: ~f~%" (-> obj data)) obj ) ;; definition for method of type bfloat (defmethod print bfloat ((obj bfloat)) - (format '#t "~f" (-> obj data)) + (format #t "~f" (-> obj data)) obj ) ;; definition for method of type type ;; INFO: Return type mismatch uint vs int. (defmethod asize-of type ((obj type)) - (the-as int (logand (l.d L346) (+ (shl (-> obj allocated-length) 2) 43))) + (the-as int (logand #xfffffff0 (+ (shl (-> obj allocated-length) 2) 43))) ) ;; definition for function basic-type? @@ -223,7 +232,7 @@ (set! end-type object) (until (begin (set! obj-type (-> obj-type parent)) (= obj-type end-type)) - (if (= obj-type parent-type) (return '#t)) + (if (= obj-type parent-type) (return #t)) ) #f ) @@ -237,7 +246,7 @@ (set! child-type (-> child-type parent)) (or (= child-type end-type) (zero? child-type)) ) - (if (= child-type parent-type) (return '#t)) + (if (= child-type parent-type) (return #t)) ) #f ) @@ -464,7 +473,7 @@ (when (and (or (not compare-result) (> (the-as int compare-result) 0)) - (!= compare-result '#t) + (!= compare-result #t) ) (+! unsorted-count 1) (set! (car iter) seoncd-elt) @@ -494,9 +503,9 @@ ;; definition for method of type inline-array-class (defmethod inspect inline-array-class ((obj inline-array-class)) - (format '#t "[~8x] ~A~%" obj (-> obj type)) - (format '#t "~Tlength: ~D~%" (-> obj length)) - (format '#t "~Tallocated-length: ~D~%" (-> obj allocated-length)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tlength: ~D~%" (-> obj length)) + (format #t "~Tallocated-length: ~D~%" (-> obj allocated-length)) obj ) @@ -599,7 +608,7 @@ (i int) (t9-10 (function _varargs_ object)) ) - (format '#t "#(") + (format #t "#(") (cond ((type-type? (-> obj content-type) integer) (set! content-type-sym (-> obj content-type symbol)) @@ -608,7 +617,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t (if (zero? i) "~D" " ~D") (-> (the-as (array int32) obj) i)) + (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int32) obj) i)) (+! i 1) ) ) @@ -616,7 +625,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t (if (zero? i) "~D" " ~D") (-> (the-as (array uint32) obj) i)) + (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array uint32) obj) i)) (+! i 1) ) ) @@ -624,7 +633,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t (if (zero? i) "~D" " ~D") (-> (the-as (array int64) obj) i)) + (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int64) obj) i)) (+! i 1) ) ) @@ -633,7 +642,7 @@ (while (< i (-> obj length)) (format - '#t + #t (if (zero? i) "#x~X" " #x~X") (-> (the-as (array uint64) obj) i) ) @@ -644,7 +653,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t (if (zero? i) "~D" " ~D") (-> (the-as (array int8) obj) i)) + (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int8) obj) i)) (+! i 1) ) ) @@ -652,7 +661,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t (if (zero? i) "~D" " ~D") (-> (the-as (array uint8) obj) i)) + (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array uint8) obj) i)) (+! i 1) ) ) @@ -660,7 +669,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t (if (zero? i) "~D" " ~D") (-> (the-as (array int16) obj) i)) + (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int16) obj) i)) (+! i 1) ) ) @@ -668,7 +677,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t (if (zero? i) "~D" " ~D") (-> (the-as (array uint16) obj) i)) + (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array uint16) obj) i)) (+! i 1) ) ) @@ -679,7 +688,7 @@ (while (< i (-> obj length)) (set! t9-10 format) - (set! a0-21 '#t) + (set! a0-21 #t) (set! a1-11 (if (zero? i) "#x~X" " #x~X")) (set! v1-42 (+ (shl i 4) (the-as int (the-as (array uint128) obj)))) (.lq a2-8 12 v1-42) @@ -691,11 +700,7 @@ (set! i 0) (while (< i (-> obj length)) - (format - '#t - (if (zero? i) "~D" " ~D") - (-> (the-as (array int32) obj) i) - ) + (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int32) obj) i)) (+! i 1) ) ) @@ -711,8 +716,8 @@ (< i (-> obj length)) (if (zero? i) - (format '#t "~f" (-> (the-as (array float) obj) i)) - (format '#t " ~f" (-> (the-as (array float) obj) i)) + (format #t "~f" (-> (the-as (array float) obj) i)) + (format #t " ~f" (-> (the-as (array float) obj) i)) ) (+! i 1) ) @@ -723,8 +728,8 @@ (< i (-> obj length)) (if (zero? i) - (format '#t "~A" (-> (the-as (array basic) obj) i)) - (format '#t " ~A" (-> (the-as (array basic) obj) i)) + (format #t "~A" (-> (the-as (array basic) obj) i)) + (format #t " ~A" (-> (the-as (array basic) obj) i)) ) (+! i 1) ) @@ -732,7 +737,7 @@ ) ) ) - (format '#t ")") + (format #t ")") obj ) @@ -759,11 +764,11 @@ (i int) (t9-14 (function _varargs_ object)) ) - (format '#t "[~8x] ~A~%" obj (-> obj type)) - (format '#t "~Tallocated-length: ~D~%" (-> obj allocated-length)) - (format '#t "~Tlength: ~D~%" (-> obj length)) - (format '#t "~Tcontent-type: ~A~%" (-> obj content-type)) - (format '#t "~Tdata[~D]: @ #x~X~%" (-> obj allocated-length) (-> obj data)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tallocated-length: ~D~%" (-> obj allocated-length)) + (format #t "~Tlength: ~D~%" (-> obj length)) + (format #t "~Tcontent-type: ~A~%" (-> obj content-type)) + (format #t "~Tdata[~D]: @ #x~X~%" (-> obj allocated-length) (-> obj data)) (cond ((type-type? (-> obj content-type) integer) (set! content-type-sym (-> obj content-type symbol)) @@ -772,7 +777,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~D~%" i (-> (the-as (array int32) obj) i)) + (format #t "~T [~D] ~D~%" i (-> (the-as (array int32) obj) i)) (+! i 1) ) ) @@ -780,7 +785,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~D~%" i (-> (the-as (array uint32) obj) i)) + (format #t "~T [~D] ~D~%" i (-> (the-as (array uint32) obj) i)) (+! i 1) ) ) @@ -788,7 +793,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~D~%" i (-> (the-as (array int64) obj) i)) + (format #t "~T [~D] ~D~%" i (-> (the-as (array int64) obj) i)) (+! i 1) ) ) @@ -796,7 +801,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] #x~X~%" i (-> (the-as (array uint64) obj) i)) + (format #t "~T [~D] #x~X~%" i (-> (the-as (array uint64) obj) i)) (+! i 1) ) ) @@ -804,7 +809,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~D~%" i (-> (the-as (array int8) obj) i)) + (format #t "~T [~D] ~D~%" i (-> (the-as (array int8) obj) i)) (+! i 1) ) ) @@ -812,7 +817,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~D~%" i (-> (the-as (array int8) obj) i)) + (format #t "~T [~D] ~D~%" i (-> (the-as (array int8) obj) i)) (+! i 1) ) ) @@ -820,7 +825,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~D~%" i (-> (the-as (array int16) obj) i)) + (format #t "~T [~D] ~D~%" i (-> (the-as (array int16) obj) i)) (+! i 1) ) ) @@ -828,7 +833,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~D~%" i (-> (the-as (array uint16) obj) i)) + (format #t "~T [~D] ~D~%" i (-> (the-as (array uint16) obj) i)) (+! i 1) ) ) @@ -839,7 +844,7 @@ (while (< i (-> obj length)) (set! t9-14 format) - (set! a0-25 '#t) + (set! a0-25 #t) (set! a1-15 "~T [~D] #x~X~%") (set! a2-13 i) (set! v1-42 (+ (shl i 4) (the-as int obj))) @@ -852,7 +857,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~D~%" i (-> obj i)) + (format #t "~T [~D] ~D~%" i (-> obj i)) (+! i 1) ) ) @@ -866,7 +871,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~f~%" i (-> obj i)) + (format #t "~T [~D] ~f~%" i (-> obj i)) (+! i 1) ) ) @@ -874,7 +879,7 @@ (set! i 0) (while (< i (-> obj length)) - (format '#t "~T [~D] ~A~%" i (-> obj i)) + (format #t "~T [~D] ~A~%" i (-> obj i)) (+! i 1) ) ) @@ -1007,8 +1012,8 @@ (if (= x 1) 1 (* x (fact (+ x -1)))) ) -;; failed to figure out what this is: -(set! *print-column* 0) +;; definition for symbol *print-column*, type binteger +(define *print-column* (the-as binteger 0)) ;; definition for function print (defun print ((arg0 object)) @@ -1020,7 +1025,7 @@ (local-vars (a0-1 object)) (set! a0-1 arg0) ((method-of-type (rtype-of a0-1) print) a0-1) - (format '#t "~%") + (format #t "~%") arg0 ) @@ -1049,8 +1054,8 @@ #f ) -;; failed to figure out what this is: -(set! *trace-list* '()) +;; definition for symbol *trace-list*, type pair +(define *trace-list* '()) ;; definition for function print-tree-bitmask (defun print-tree-bitmask ((bits int) (count int)) @@ -1058,7 +1063,7 @@ (set! i 0) (while (< i count) - (if (zero? (logand bits 1)) (format '#t " ") (format '#t "| ")) + (if (zero? (logand bits 1)) (format #t " ") (format #t "| ")) (set! bits (shr bits 1)) (+! i 1) ) @@ -1126,10 +1131,10 @@ ) #f ) - (else '#t) + (else #t) ) ) - ((and allow-false (not obj)) '#t) + ((and allow-false (not obj)) #t) (else (cond ((= expected-type structure) @@ -1167,7 +1172,7 @@ ) #f ) - (else '#t) + (else #t) ) ) ((= expected-type pair) @@ -1198,12 +1203,12 @@ ) #f ) - (else '#t) + (else #t) ) ) ((= expected-type binteger) (cond - ((zero? (logand (the-as int obj) 7)) '#t) + ((zero? (logand (the-as int obj) 7)) #t) (else (if name @@ -1261,10 +1266,7 @@ ) (else (cond - ((and - (!= expected-type type) - (not (valid? (rtype-of obj) type #f '#t 0)) - ) + ((and (!= expected-type type) (not (valid? (rtype-of obj) type #f #t 0))) (if name (format @@ -1309,7 +1311,7 @@ ) #f ) - (else '#t) + (else #t) ) ) ((begin @@ -1329,7 +1331,7 @@ ) #f ) - (else '#t) + (else #t) ) ) ) diff --git a/test/decompiler/test_AtomicOpBuilder.cpp b/test/decompiler/test_AtomicOpBuilder.cpp index c174a35e8f..a518f35634 100644 --- a/test/decompiler/test_AtomicOpBuilder.cpp +++ b/test/decompiler/test_AtomicOpBuilder.cpp @@ -299,7 +299,7 @@ TEST(DecompilerAtomicOpBuilder, DADDIU) { test_case(assembly_from_list({"daddiu a1, s7, -10"}), {"(set! a1 '())"}, {{"a1"}}, {{}}, {{}}); test_case(assembly_from_list({"daddiu a1, s7, -32768"}), {"(set! a1 __START-OF-TABLE__)"}, {{"a1"}}, {{}}, {{}}); - test_case(assembly_from_list({"daddiu a1, s7, 8"}), {"(set! a1 '#t)"}, {{"a1"}}, {{}}, {{}}); + test_case(assembly_from_list({"daddiu a1, s7, 8"}), {"(set! a1 #t)"}, {{"a1"}}, {{}}, {{}}); test_case(assembly_from_list({"L123:", "daddiu a1, fp, L123"}), {"(set! a1 L123)"}, {{"a1"}}, {{}}, {{}}); test_case(assembly_from_list({"daddiu a1, a2, 1234"}), {"(set! a1 (+ a2 1234))"}, {{"a1"}}, diff --git a/test/decompiler/test_FormBeforeExpressions.cpp b/test/decompiler/test_FormBeforeExpressions.cpp index 34c466963d..5001c9704b 100644 --- a/test/decompiler/test_FormBeforeExpressions.cpp +++ b/test/decompiler/test_FormBeforeExpressions.cpp @@ -188,7 +188,7 @@ TEST_F(FormRegressionTest, FormatString) { std::string expected = "(begin\n" " (set! t9-0 format)\n" - " (set! a0-1 '#t)\n" + " (set! a0-1 #t)\n" " (set! a1-0 L343)\n" " (set! f0-0 (-> a0-0 data))\n" " (set! a2-0 (fpr->gpr f0-0))\n" @@ -233,7 +233,7 @@ TEST_F(FormRegressionTest, WhileLoop) { " (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n" " (if\n" " (= v1-0 a1-0)\n" - " (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)))\n" + " (return (begin (set! v1-1 #t) (set! v0-0 v1-1)))\n" " )\n" " )\n" " (set! v0-0 #f)\n" @@ -299,7 +299,7 @@ TEST_F(FormRegressionTest, Or) { " )\n" " (if\n" " (= a0-0 a1-0)\n" - " (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)))\n" + " (return (begin (set! v1-1 #t) (set! v0-0 v1-1)))\n" " )\n" " )\n" " (set! v0-0 #f)\n" @@ -726,7 +726,7 @@ TEST_F(FormRegressionTest, NestedAndOr) { " )\n" " a0-2\n" // false or >0 " )\n" - " (begin (set! a0-3 '#t) (set! v1-2 (!= v1-1 a0-3)))\n" // not #t + " (begin (set! a0-3 #t) (set! v1-2 (!= v1-1 a0-3)))\n" // not #t " )\n" " v1-2\n" // (and (or false >0) (not #t)) " )\n" diff --git a/test/decompiler/test_FormExpressionBuild.cpp b/test/decompiler/test_FormExpressionBuild.cpp index 41005a77a0..aa33cfcb6e 100644 --- a/test/decompiler/test_FormExpressionBuild.cpp +++ b/test/decompiler/test_FormExpressionBuild.cpp @@ -371,7 +371,7 @@ TEST_F(FormRegressionTest, ExprTrue) { " jr ra\n" " daddu sp, sp, r0"; std::string type = "(function symbol)"; - std::string expected = "'#t"; + std::string expected = "#t"; test_with_expr(func, type, expected); } @@ -401,7 +401,7 @@ TEST_F(FormRegressionTest, ExprPrintBfloat) { " daddiu sp, sp, 32"; std::string type = "(function bfloat bfloat)"; - std::string expected = "(begin (format (quote #t) \"~f\" (-> arg0 data)) arg0)"; + std::string expected = "(begin (format #t \"~f\" (-> arg0 data)) arg0)"; test_with_expr(func, type, expected, false, "", {{"L343", "~f"}}); } @@ -461,7 +461,7 @@ TEST_F(FormRegressionTest, ExprBasicTypeP) { // don't plan on supporting this. " (if\n" " (= v1-0 arg1)\n" - " (return '#t)\n" + " (return #t)\n" " )\n" " )\n" " #f\n" @@ -505,7 +505,7 @@ TEST_F(FormRegressionTest, FinalBasicTypeP) { " (set! a0-1 object)\n" " (until\n" " (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n" - " (if (= v1-0 arg1) (return (quote #t)))\n" + " (if (= v1-0 arg1) (return #t))\n" " )\n" " #f\n" " )"; @@ -559,7 +559,7 @@ TEST_F(FormRegressionTest, ExprTypeTypep) { " (set! arg0 (-> arg0 parent))\n" " (or (= arg0 v1-0) (zero? arg0))\n" " )\n" - " (if (= arg0 arg1) (return '#t))\n" + " (if (= arg0 arg1) (return #t))\n" " )\n" " #f\n" " )"; @@ -1581,7 +1581,7 @@ TEST_F(FormRegressionTest, ExprSort) { " (set! s1-0 (car (cdr s3-0)))\n" " (set! v1-1 (arg1 s2-0 s1-0))\n" " (when\n" - " (and (or (not v1-1) (> (the-as int v1-1) 0)) (!= v1-1 (quote #t)))\n" + " (and (or (not v1-1) (> (the-as int v1-1) 0)) (!= v1-1 #t))\n" " (+! s4-0 1)\n" " (set! (car s3-0) s1-0)\n" " (set! (car (cdr s3-0)) s2-0)\n" @@ -2078,7 +2078,7 @@ TEST_F(FormRegressionTest, ExprPrintl) { "(begin\n" " (set! a0-1 arg0)\n" " ((method-of-type (rtype-of a0-1) print) a0-1)\n" - " (format (quote #t) \"~%\")\n" + " (format #t \"~%\")\n" " arg0\n" " )"; test_with_expr(func, type, expected, false, "", {{"L324", "~%"}}); @@ -2178,8 +2178,8 @@ TEST_F(FormRegressionTest, ExprPrintTreeBitmask) { " (< s4-0 arg1)\n" " (if\n" " (zero? (logand arg0 1))\n" - " (format (quote #t) \" \")\n" - " (format (quote #t) \"| \")\n" + " (format #t \" \")\n" + " (format #t \"| \")\n" " )\n" " (set! arg0 (shr arg0 1))\n" " (+! s4-0 1)\n" @@ -2294,7 +2294,7 @@ TEST_F(FormRegressionTest, ExprPrintName) { std::string expected = "(cond\n" - " ((= arg0 arg1) (quote #t))\n" + " ((= arg0 arg1) #t)\n" " ((and (= (-> arg0 type) string) (= (-> arg1 type) string))\n" " (string= (the-as string arg0) (the-as string arg1))\n" " )\n" @@ -2496,7 +2496,7 @@ TEST_F(FormRegressionTest, StringLt) { " (while\n" " (< v1-4 s4-1)\n" " (cond\n" - " ((< (-> arg0 data v1-4) (-> arg1 data v1-4)) (return (quote #t)))\n" + " ((< (-> arg0 data v1-4) (-> arg1 data v1-4)) (return #t))\n" " ((< (-> arg1 data v1-4) (-> arg0 data v1-4)) (return #f))\n" " )\n" " (+! v1-4 1)\n" @@ -2533,7 +2533,7 @@ TEST_F(FormRegressionTest, ExprAssert) { " daddiu sp, sp, 16"; std::string type = "(function symbol string int)"; - std::string expected = "(begin (if (not arg0) (format (quote #t) \"A ~A\" arg1)) 0)"; + std::string expected = "(begin (if (not arg0) (format #t \"A ~A\" arg1)) 0)"; test_with_expr(func, type, expected, false, "", {{"L17", "A ~A"}}); } diff --git a/test/decompiler/test_FormExpressionBuildLong.cpp b/test/decompiler/test_FormExpressionBuildLong.cpp index 295cf92fba..b248c821df 100644 --- a/test/decompiler/test_FormExpressionBuildLong.cpp +++ b/test/decompiler/test_FormExpressionBuildLong.cpp @@ -538,7 +538,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { std::string expected = "(begin\n" - " (format (quote #t) \"#(\")\n" + " (format #t \"#(\")\n" " (cond\n" " ((type-type? (-> arg0 content-type) integer)\n" " (set! v1-1 (-> arg0 content-type symbol))\n" @@ -548,7 +548,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-0 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-0) \"~D\" \" ~D\")\n" " (-> (the-as (array int32) arg0) s5-0)\n" " )\n" @@ -560,7 +560,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-1 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-1) \"~D\" \" ~D\")\n" " (-> (the-as (array uint32) arg0) s5-1)\n" " )\n" @@ -572,7 +572,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-2 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-2) \"~D\" \" ~D\")\n" " (-> (the-as (array int64) arg0) s5-2)\n" " )\n" @@ -584,7 +584,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-3 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-3) \"#x~X\" \" #x~X\")\n" " (-> (the-as (array uint64) arg0) s5-3)\n" " )\n" @@ -596,7 +596,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-4 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-4) \"~D\" \" ~D\")\n" " (-> (the-as (array int8) arg0) s5-4)\n" " )\n" @@ -608,7 +608,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-5 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-5) \"~D\" \" ~D\")\n" " (-> (the-as (array uint8) arg0) s5-5)\n" " )\n" @@ -620,7 +620,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-6 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-6) \"~D\" \" ~D\")\n" " (-> (the-as (array int16) arg0) s5-6)\n" " )\n" @@ -632,7 +632,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-7 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-7) \"~D\" \" ~D\")\n" " (-> (the-as (array uint16) arg0) s5-7)\n" " )\n" @@ -646,7 +646,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-8 (-> arg0 length))\n" " (set! t9-10 format)\n" - " (set! a0-21 (quote #t))\n" + " (set! a0-21 #t)\n" " (set! a1-11 (if (zero? s5-8) \"#x~X\" \" #x~X\"))\n" " (set!\n" " v1-42\n" @@ -662,7 +662,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (while\n" " (< s5-9 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " (if (zero? s5-9) \"~D\" \" ~D\")\n" " (-> (the-as (array int32) arg0) s5-9)\n" " )\n" @@ -681,8 +681,8 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (< s5-10 (-> arg0 length))\n" " (if\n" " (zero? s5-10)\n" - " (format (quote #t) \"~f\" (-> (the-as (array float) arg0) s5-10))\n" - " (format (quote #t) \" ~f\" (-> (the-as (array float) arg0) s5-10))\n" + " (format #t \"~f\" (-> (the-as (array float) arg0) s5-10))\n" + " (format #t \" ~f\" (-> (the-as (array float) arg0) s5-10))\n" " )\n" " (+! s5-10 1)\n" " )\n" @@ -693,8 +693,8 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (< s5-11 (-> arg0 length))\n" " (if\n" " (zero? s5-11)\n" - " (format (quote #t) \"~A\" (-> (the-as (array basic) arg0) s5-11))\n" - " (format (quote #t) \" ~A\" (-> (the-as (array basic) arg0) s5-11))\n" + " (format #t \"~A\" (-> (the-as (array basic) arg0) s5-11))\n" + " (format #t \" ~A\" (-> (the-as (array basic) arg0) s5-11))\n" " )\n" " (+! s5-11 1)\n" " )\n" @@ -702,7 +702,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " )\n" " )\n" " )\n" - " (format (quote #t) \")\")\n" + " (format #t \")\")\n" " arg0\n" " )"; test_with_expr(func, type, expected, true, "array", @@ -1188,12 +1188,12 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { std::string expected = "(begin\n" - " (format (quote #t) \"[~8x] ~A~%\" arg0 (-> arg0 type))\n" - " (format (quote #t) \"~Tallocated-length: ~D~%\" (-> arg0 allocated-length))\n" - " (format (quote #t) \"~Tlength: ~D~%\" (-> arg0 length))\n" - " (format (quote #t) \" ~Tcontent-type: ~A~%\" (-> arg0 content-type))\n" + " (format #t \"[~8x] ~A~%\" arg0 (-> arg0 type))\n" + " (format #t \"~Tallocated-length: ~D~%\" (-> arg0 allocated-length))\n" + " (format #t \"~Tlength: ~D~%\" (-> arg0 length))\n" + " (format #t \" ~Tcontent-type: ~A~%\" (-> arg0 content-type))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~Tdata[~D]: @ #x~X~%\"\n" " (-> arg0 allocated-length)\n" " (-> arg0 data)\n" @@ -1207,7 +1207,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-0 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~D~%\"\n" " s5-0\n" " (-> (the-as (array int32) arg0) s5-0)\n" @@ -1220,7 +1220,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-1 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~D~%\"\n" " s5-1\n" " (-> (the-as (array uint32) arg0) s5-1)\n" @@ -1233,7 +1233,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-2 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~D~%\"\n" " s5-2\n" " (-> (the-as (array int64) arg0) s5-2)\n" @@ -1246,7 +1246,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-3 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] #x~X~%\"\n" " s5-3\n" " (-> (the-as (array uint64) arg0) s5-3)\n" @@ -1259,7 +1259,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-4 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~D~%\"\n" " s5-4\n" " (-> (the-as (array int8) arg0) s5-4)\n" @@ -1272,7 +1272,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-5 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~D~%\"\n" " s5-5\n" " (-> (the-as (array int8) arg0) s5-5)\n" @@ -1285,7 +1285,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-6 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~D~%\"\n" " s5-6\n" " (-> (the-as (array int16) arg0) s5-6)\n" @@ -1298,7 +1298,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-7 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~D~%\"\n" " s5-7\n" " (-> (the-as (array uint16) arg0) s5-7)\n" @@ -1313,7 +1313,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-8 (-> arg0 length))\n" " (set! t9-14 format)\n" - " (set! a0-25 (quote #t))\n" + " (set! a0-25 #t)\n" " (set! a1-15 \"~T [~D] #x~X~%\")\n" " (set! a2-13 s5-8)\n" " (set!\n" @@ -1329,7 +1329,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (set! s5-9 0)\n" " (while\n" " (< s5-9 (-> arg0 length))\n" - " (format (quote #t) \"~T [~D] ~D~%\" s5-9 (-> arg0 s5-9))\n" + " (format #t \"~T [~D] ~D~%\" s5-9 (-> arg0 s5-9))\n" " (+! s5-9 1)\n" " )\n" " )\n" @@ -1344,7 +1344,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-10 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~f~%\"\n" " s5-10\n" " (-> (the-as (array float) arg0) s5-10)\n" @@ -1357,7 +1357,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-11 (-> arg0 length))\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~D] ~A~%\"\n" " s5-11\n" " (-> (the-as (array basic) arg0) s5-11)\n" @@ -1954,10 +1954,10 @@ TEST_F(FormRegressionTest, ExprValid) { " )\n" " #f\n" " )\n" - " (else (quote #t))\n" + " (else #t)\n" " )\n" " )\n" - " ((and arg3 (not arg0)) (quote #t))\n" + " ((and arg3 (not arg0)) #t)\n" " (else\n" " (cond\n" " ((= arg1 structure)\n" @@ -1995,7 +1995,7 @@ TEST_F(FormRegressionTest, ExprValid) { " )\n" " #f\n" " )\n" - " (else (quote #t))\n" + " (else #t)\n" " )\n" " )\n" " ((= arg1 pair)\n" @@ -2026,12 +2026,12 @@ TEST_F(FormRegressionTest, ExprValid) { " )\n" " #f\n" " )\n" - " (else (quote #t))\n" + " (else #t)\n" " )\n" " )\n" " ((= arg1 binteger)\n" " (cond\n" - " ((zero? (logand (the-as int arg0) 7)) (quote #t))\n" + " ((zero? (logand (the-as int arg0) 7)) #t)\n" " (else\n" " (if\n" " arg2\n" @@ -2092,7 +2092,7 @@ TEST_F(FormRegressionTest, ExprValid) { " (cond\n" " ((and\t\n" " (!= arg1 type)\t\n" - " (not (valid? (rtype-of arg0) type #f (quote #t) 0))\t\n" + " (not (valid? (rtype-of arg0) type #f #t 0))\t\n" " )\n" " (if\n" " arg2\n" @@ -2141,7 +2141,7 @@ TEST_F(FormRegressionTest, ExprValid) { " )\n" " #f\n" " )\n" - " (else (quote #t))\n" + " (else #t)\n" " )\n" " )\n" " ((begin\n" @@ -2162,7 +2162,7 @@ TEST_F(FormRegressionTest, ExprValid) { " )\n" " #f\n" " )\n" - " (else (quote #t))\n" + " (else #t)\n" " )\n" " )\n" " )\n" @@ -2489,7 +2489,7 @@ TEST_F(FormRegressionTest, ExprStringToInt) { " (set! a0-3 (&-> a0-2 1))\n" " (when\n" " (= (-> a0-3 1) 45)\n" - " (set! v1-0 (quote #t))\n" + " (set! v1-0 #t)\n" " (set! a0-3 (&-> a0-3 1))\n" " (set! a1-8 a0-3)\n" " )\n" @@ -2548,7 +2548,7 @@ TEST_F(FormRegressionTest, ExprStringToInt) { " (else\n" " (when\n" " (= (-> a0-1 1) 45)\n" - " (set! v1-0 (quote #t))\n" + " (set! v1-0 #t)\n" " (set! a0-1 (&-> a0-1 1))\n" " (set! a1-47 a0-1)\n" " )\n" diff --git a/test/decompiler/test_gkernel_decomp.cpp b/test/decompiler/test_gkernel_decomp.cpp index a11b144eb2..d5a579cf74 100644 --- a/test/decompiler/test_gkernel_decomp.cpp +++ b/test/decompiler/test_gkernel_decomp.cpp @@ -167,7 +167,7 @@ TEST_F(FormRegressionTest, ExprMethod2Thread) { std::string expected = "(begin\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"#<~A ~S of ~S pc: #x~X @ #x~X>\"\n" " (-> arg0 type)\n" " (-> arg0 name)\n" @@ -522,21 +522,21 @@ TEST_F(FormRegressionTest, RemoveMethod3ProcessTree) { // gross, but expected. see https://github.com/water111/jak-project/issues/254 std::string expected = "(begin\n" - " (format (quote #t) \"[~8x] ~A~%\" arg0 (-> arg0 type))\n" - " (format (quote #t) \"~Tname: ~S~%\" (-> arg0 name))\n" - " (format (quote #t) \"~Tmask: #x~X~%\" (-> arg0 mask))\n" + " (format #t \"[~8x] ~A~%\" arg0 (-> arg0 type))\n" + " (format #t \"~Tname: ~S~%\" (-> arg0 name))\n" + " (format #t \"~Tmask: #x~X~%\" (-> arg0 mask))\n" " (set! t9-3 format)\n" - " (set! a0-4 (quote #t))\n" + " (set! a0-4 #t)\n" " (set! a1-3 \"~Tparent: ~A~%\")\n" " (set! v1-0 (-> arg0 parent))\n" " (t9-3 a0-4 a1-3 (if v1-0 (-> v1-0 0 self)))\n" " (set! t9-4 format)\n" - " (set! a0-5 (quote #t))\n" + " (set! a0-5 #t)\n" " (set! a1-4 \"~Tbrother: ~A~%\")\n" " (set! v1-2 (-> arg0 brother))\n" " (t9-4 a0-5 a1-4 (if v1-2 (-> v1-2 0 self)))\n" " (set! t9-5 format)\n" - " (set! a0-6 (quote #t))\n" + " (set! a0-6 #t)\n" " (set! a1-5 \"~Tchild: ~A~%\")\n" " (set! v1-4 (-> arg0 child))\n" " (t9-5 a0-6 a1-5 (if v1-4 (-> v1-4 0 self)))\n" @@ -799,7 +799,7 @@ TEST_F(FormRegressionTest, ExprMethod2Process) { std::string expected = "(begin\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"#<~A ~S ~A :state ~S \"\n" " (-> arg0 type)\n" " (-> arg0 name)\n" @@ -807,7 +807,7 @@ TEST_F(FormRegressionTest, ExprMethod2Process) { " (if (-> arg0 state) (-> arg0 state name))\n" " )\n" " (format\n" - " (quote #t)\n" + " #t\n" " \":stack ~D/~D :heap ~D/~D @ #x~X>\"\n" " (- (-> arg0 top-thread stack-top) (the-as uint (-> arg0 top-thread sp)))\n" " (-> arg0 main-thread stack-size)\n" @@ -1530,7 +1530,7 @@ TEST_F(FormRegressionTest, ExprMethod3DeadPoolHeap) { " (if (-> arg0 alive-list prev) (gap-size arg0 (-> arg0 alive-list prev)) s5-0)\n" " )\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~Tprocess-list[0] @ #x~X ~D/~D bytes used~%\"\n" " (-> arg0 process-list)\n" " (- s5-0 v1-3)\n" @@ -1543,7 +1543,7 @@ TEST_F(FormRegressionTest, ExprMethod3DeadPoolHeap) { " (if\n" " (-> s5-1 process)\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T [~3D] # ~A~%\"\n" " s4-0\n" " s5-1\n" @@ -1554,7 +1554,7 @@ TEST_F(FormRegressionTest, ExprMethod3DeadPoolHeap) { " (if\n" " (nonzero? s3-0)\n" " (format\n" - " (quote #t)\n" + " #t\n" " \"~T gap: ~D bytes @ #x~X~%\"\n" " s3-0\n" " (gap-location arg0 s5-1)\n" diff --git a/test/offline/offline_test_main.cpp b/test/offline/offline_test_main.cpp index eb8b4b664f..5ad2167c13 100644 --- a/test/offline/offline_test_main.cpp +++ b/test/offline/offline_test_main.cpp @@ -7,19 +7,12 @@ #include "decompiler/ObjectFile/ObjectFileDB.h" #include "goalc/compiler/Compiler.h" -int main(int argc, char** argv) { - lg::initialize(); - - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} - namespace { // the object files to test -const std::unordered_set object_files_to_decompile = {"gcommon"}; +const std::unordered_set g_object_files_to_decompile = {"gcommon"}; // the object files to check against a reference in test/decompiler/reference -const std::unordered_set object_files_to_check_against_reference = { +const std::unordered_set g_object_files_to_check_against_reference = { "gcommon" // NOTE: this file needs work, but adding it for now just to test the framework. }; @@ -47,9 +40,34 @@ const std::unordered_set expected_skip_in_decompiler = { const std::unordered_set skip_in_compiling = { // these functions are not implemented by the compiler in OpenGOAL, but are in GOAL. - "abs", "ash", "min", "max", "lognor"}; + "abs", "ash", "min", "max", "lognor", "(method 3 vec4s)", "(method 2 vec4s)"}; + +// default location for the data. It can be changed with a command line argument. +std::string g_iso_data_path = ""; } // namespace +int main(int argc, char** argv) { + lg::initialize(); + + // look for an argument that's not a gtest option + bool got_arg = false; + for (int i = 1; i < argc; i++) { + auto arg = std::string(argv[i]); + if (arg.length() > 2 && arg[0] == '-' && arg[1] == '-') { + continue; + } + if (got_arg) { + printf("You can only specify a single path for ISO data\n"); + return 1; + } + g_iso_data_path = arg; + lg::warn("Using path {} for iso_data", g_iso_data_path); + got_arg = true; + } + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} class OfflineDecompilation : public ::testing::Test { protected: @@ -62,11 +80,22 @@ class OfflineDecompilation : public ::testing::Test { decompiler::set_config( file_util::get_file_path({"decompiler", "config", "jak1_ntsc_black_label.jsonc"})); - decompiler::get_config().allowed_objects = object_files_to_decompile; + decompiler::get_config().allowed_objects = g_object_files_to_decompile; + + std::vector dgos = {"CGO/KERNEL.CGO", "CGO/ENGINE.CGO"}; + std::vector dgo_paths; + if (g_iso_data_path.empty()) { + for (auto& x : dgos) { + dgo_paths.push_back(file_util::get_file_path({"iso_data", x})); + } + } else { + for (auto& x : dgos) { + dgo_paths.push_back(file_util::combine_path(g_iso_data_path, x)); + } + } + db = std::make_unique( - std::vector{file_util::get_file_path({"iso_data", "CGO", "KERNEL.CGO"}), - file_util::get_file_path({"iso_data", "CGO", "ENGINE.CGO"})}, - decompiler::get_config().obj_file_name_map_file, std::vector{}, + dgo_paths, decompiler::get_config().obj_file_name_map_file, std::vector{}, std::vector{}); // basic processing to find functions/data/disassembly @@ -273,7 +302,7 @@ void strip_trailing_newlines(std::string& in) { } // namespace TEST_F(OfflineDecompilation, Reference) { - for (auto& file : object_files_to_check_against_reference) { + for (auto& file : g_object_files_to_check_against_reference) { auto& obj_l = db->obj_files_by_name.at(file); ASSERT_EQ(obj_l.size(), 1); @@ -292,7 +321,7 @@ TEST_F(OfflineDecompilation, Reference) { TEST_F(OfflineDecompilation, Compile) { Compiler compiler; - for (auto& file : object_files_to_check_against_reference) { + for (auto& file : g_object_files_to_check_against_reference) { auto& obj_l = db->obj_files_by_name.at(file); ASSERT_EQ(obj_l.size(), 1); diff --git a/test/test_goos.cpp b/test/test_goos.cpp index d67d65a47e..c5fb8415fc 100644 --- a/test/test_goos.cpp +++ b/test/test_goos.cpp @@ -151,7 +151,7 @@ TEST(GoosBuiltins, Addition) { Interpreter i; // single element adding EXPECT_EQ(e(i, "(+ 1)"), "1"); - EXPECT_EQ(e(i, "(+ 1.)"), "1.000000"); + EXPECT_EQ(e(i, "(+ 1.)"), "1.0"); // two element adding EXPECT_EQ(e(i, "(+ 1 2)"), "3"); @@ -174,7 +174,7 @@ TEST(GoosBuiltins, Multiplication) { Interpreter i; // single element adding EXPECT_EQ(e(i, "(* 2)"), "2"); - EXPECT_EQ(e(i, "(* 2.)"), "2.000000"); + EXPECT_EQ(e(i, "(* 2.)"), "2.0"); // two element adding EXPECT_EQ(e(i, "(* 3 2)"), "6"); @@ -197,7 +197,7 @@ TEST(GoosBuiltins, Subtraction) { Interpreter i; // single element adding EXPECT_EQ(e(i, "(- 2)"), "-2"); - EXPECT_EQ(e(i, "(- 2.)"), "-2.000000"); + EXPECT_EQ(e(i, "(- 2.)"), "-2.0"); // two element adding EXPECT_EQ(e(i, "(- 3 2)"), "1"); diff --git a/test/test_type_system.cpp b/test/test_type_system.cpp index 73b895af2c..153ffbbd16 100644 --- a/test/test_type_system.cpp +++ b/test/test_type_system.cpp @@ -239,7 +239,7 @@ TEST(TypeSystem, MethodSubstitute) { namespace { bool ts_name_name(TypeSystem& ts, const std::string& ex, const std::string& act) { - return ts.typecheck(ts.make_typespec(ex), ts.make_typespec(act), "", false, false); + return ts.typecheck_and_throw(ts.make_typespec(ex), ts.make_typespec(act), "", false, false); } } // namespace @@ -260,17 +260,17 @@ TEST(TypeSystem, TypeCheck) { auto f_b_n = ts.make_function_typespec({"basic"}, "none"); // complex - EXPECT_TRUE(ts.typecheck(f, f_s_n)); - EXPECT_TRUE(ts.typecheck(f_s_n, f_s_n)); - EXPECT_TRUE(ts.typecheck(f_b_n, f_s_n)); + EXPECT_TRUE(ts.typecheck_and_throw(f, f_s_n)); + EXPECT_TRUE(ts.typecheck_and_throw(f_s_n, f_s_n)); + EXPECT_TRUE(ts.typecheck_and_throw(f_b_n, f_s_n)); - EXPECT_FALSE(ts.typecheck(f_s_n, f, "", false, false)); - EXPECT_FALSE(ts.typecheck(f_s_n, f_b_n, "", false, false)); + EXPECT_FALSE(ts.typecheck_and_throw(f_s_n, f, "", false, false)); + EXPECT_FALSE(ts.typecheck_and_throw(f_s_n, f_b_n, "", false, false)); // number of parameter mismatch auto f_s_s_n = ts.make_function_typespec({"string", "string"}, "none"); - EXPECT_FALSE(ts.typecheck(f_s_n, f_s_s_n, "", false, false)); - EXPECT_FALSE(ts.typecheck(f_s_s_n, f_s_n, "", false, false)); + EXPECT_FALSE(ts.typecheck_and_throw(f_s_n, f_s_s_n, "", false, false)); + EXPECT_FALSE(ts.typecheck_and_throw(f_s_s_n, f_s_n, "", false, false)); } TEST(TypeSystem, FieldLookup) {