[decompiler] Handle find-parent-method (#3018)

This change adds a few new features:
- Decompiler automatically knows the type of `find-parent-method` use in
jak 1 and jak2 when used in a method or virtual state handler.
- Decompiler inserts a call to `call-parent-method` or
`find-parent-state`
- Removed most casts related to these functions

There are still a few minor issues around this:
- There are still some casts needed when using `post` methods, as `post`
is just a `function`, and needs a cast to `(function none)` or similar.
It didn't seem easy to change the type of `post`, so I'm not going to
worry about it for this PR. It only shows up in like 3 places in jak 2.
(and 0 in jak 1)
- If "call the handler if it's not #f" logic should probably be another
macro.

Fixes #805
This commit is contained in:
water111
2023-09-30 08:06:09 -07:00
committed by GitHub
parent 0f3782128f
commit 0e31a9c407
323 changed files with 937 additions and 1797 deletions
+36 -1
View File
@@ -2621,7 +2621,9 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
}
}
FormElement* SetFormFormElement::make_set_time(const Env& env, FormPool& pool, FormStack& stack) {
FormElement* SetFormFormElement::make_set_time(const Env& /*env*/,
FormPool& pool,
FormStack& /*stack*/) {
auto matcher = match(
Matcher::op(GenericOpMatcher::func(Matcher::constant_token("current-time")), {}), m_src);
if (matcher.matched) {
@@ -3908,6 +3910,39 @@ void FunctionCallElement::update_from_stack(const Env& env,
}
}
// detect call-parent-method
{
const auto& guessed_name = env.func->guessed_name;
if (guessed_name.kind == FunctionName::FunctionKind::METHOD) {
// detect stuff like: ((find-parent-method...) arg...)
auto mr_find_parent =
match(Matcher::func(Matcher::symbol("find-parent-method"),
{Matcher::symbol(env.func->method_of_type),
Matcher::integer(env.func->guessed_name.method_id)}),
unstacked.at(0)
);
if (mr_find_parent.matched) {
new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_function(pool.form<ConstantTokenElement>("call-parent-method")),
arg_forms);
}
} else if (guessed_name.kind == FunctionName::FunctionKind::V_STATE && arg_forms.size() == 2) {
// here, simply detect (find-parent-method...)
//
auto mr_find_parent = match(Matcher::symbol("find-parent-method"), unstacked.at(0));
if (mr_find_parent.matched) {
auto state_info =
env.dts->ts.lookup_method(guessed_name.type_name, guessed_name.state_name);
if (arg_forms.at(0)->to_string(env) == guessed_name.type_name &&
arg_forms.at(1)->to_string(env) == std::to_string(state_info.id)) {
new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_function(pool.form<ConstantTokenElement>("find-parent-state")));
}
}
}
}
result->push_back(new_form);
}