jak-project/decompiler/util/DecompilerTypeSystem.h
Tyler Wilding abf61a94fb
docs: add support for :override-doc in method declarations as well as documenting state handlers (#2139)
Adding support for better child-type method docstrings. This is a
problem unique to methods.

Usually, a child-type will have the same signature and a common name
will apply, but the implementation is different. This means, you
probably want a different docstring to describe what is happening.

Currently this is possible to do via `:replace`. The problem with
replace is two fold:
- a replaced method ends up in the generated `deftype`...because you
usually change the signature!
- we don't put docstrings in the `deftype` in normal GOAL, this is just
something we do for the `all-types` file (they go in the `defmethod`
instead)
- more importantly, this means anytime you now want to change the
parent's name/args/return type -- you have to apply that change
everywhere.

So this is a better design you can now just declare the method like so:
```clj
(:override-doc "my new docstring" <method_id>)
```

And internally a pseudo-replaced method will be added, but it will
inherit everything from the parent (except the docstring of course)

Unrelated - I also made all the keyword args for declaring methods not
depend on ordering

This also adds support for documenting virtual and non-virtual state
handlers. For example:

```clj
  (:states
    (part-tester-idle (:event "test") symbol))
```

or

```clj
(idle () _type_ :state (:event "test") 20)
```

I will probably add the ability to give some sort of over-view docstring
at a later date.

Co-authored-by: water <awaterford111445@gmail.com>
2023-01-21 20:45:45 -05:00

82 lines
3 KiB
C++

#pragma once
#include "common/goos/Reader.h"
#include "common/goos/TextDB.h"
#include "common/type_system/TypeSystem.h"
#include "decompiler/Disasm/Register.h"
namespace decompiler {
class TP_Type;
class TypeState;
class DecompilerTypeSystem {
public:
DecompilerTypeSystem(GameVersion version);
TypeSystem ts;
std::unordered_map<std::string, TypeSpec> symbol_types;
std::unordered_set<std::string> symbols;
std::vector<std::string> symbol_add_order;
// TODO - these are needed to propagate the info from the `Type` to the final result
// as only the `TypeSpec` is available at that point
std::unordered_map<std::string, DefinitionMetadata> symbol_metadata_map;
// {type_name : {method_name : {handler : doc}}}
std::unordered_map<
std::string,
std::unordered_map<std::string, std::unordered_map<std::string, DefinitionMetadata>>>
virtual_state_metadata;
// {state_name : {handler : doc}}
std::unordered_map<std::string, std::unordered_map<std::string, DefinitionMetadata>>
state_metadata;
std::unordered_map<std::string, u64> type_flags;
std::unordered_map<std::string, std::string> type_parents;
std::unordered_map<std::string, int> bad_format_strings;
std::unordered_map<std::string, std::vector<std::vector<int>>>
format_ops_with_dynamic_string_by_func_name;
std::unordered_map<std::string, std::unordered_map<int, std::string>> art_group_info;
void add_symbol(const std::string& name) {
if (symbols.find(name) == symbols.end()) {
symbols.insert(name);
symbol_add_order.push_back(name);
}
}
void add_symbol(const std::string& name,
const std::string& base_type,
const DefinitionMetadata& symbol_metadata) {
add_symbol(name, TypeSpec(base_type), symbol_metadata);
}
void add_symbol(const std::string& name,
const TypeSpec& type_spec,
const DefinitionMetadata& symbol_metadata);
void parse_type_defs(const std::vector<std::string>& file_path);
TypeSpec parse_type_spec(const std::string& str) const;
void add_type_flags(const std::string& name, u64 flags);
void add_type_parent(const std::string& child, const std::string& parent);
std::string dump_symbol_types();
std::string lookup_parent_from_inspects(const std::string& child) const;
bool lookup_flags(const std::string& type, u64* dest) const;
TP_Type tp_lca(const TP_Type& existing, const TP_Type& add, bool* changed) const;
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;
int get_dynamic_format_arg_count(const std::string& func_name, int op_idx) const;
TypeSpec lookup_symbol_type(const std::string& name) const;
bool should_attempt_cast_simplify(const TypeSpec& expected, const TypeSpec& actual) const;
// todo - totally eliminate this.
struct {
std::string current_method_type;
void reset() { current_method_type.clear(); }
} type_prop_settings;
private:
mutable goos::Reader m_reader;
};
} // namespace decompiler