mirror of
https://github.com/open-goal/jak-project
synced 2026-08-17 13:40:39 -04:00
[opengoal] make none a child of object (#3001)
Previously, `object` and `none` were both top-level types. This made decompilation rather messy as they have no LCA and resulted in a lot of variables coming out as type `none` which is very very wrong and additionally there were plenty of casts to `object`. This changes it so `none` becomes a child of `object` (it is still represented by `NullType` which remains unusable in compilation). This change makes `object` the sole top-level type, and the type that can represent *any* GOAL object. I believe this matches the original GOAL built-in type structure. A function that has a return type of `object` can now return an integer or a `none` at the same time. However, keep in mind that the return value of `(none)` is still undefined, just as before. This also makes a cast to `object` meaningless in 90% of the situations it showed up in (as every single thing is already an `object`) and the decompiler will no longer emit them. Casts to `none` are also reduced. Yay! Additionally, state handlers also don't get the final `(none)` printed out anymore. The return type of a state handler is completely meaningless outside the event handler (which is return type `object` anyway) so there are no limitations on what the last form needs to be. I did this instead of making them return `object` to trick the decompiler into not trying to output a variable to be used as a return value (internally, in the decompiler they still have return type `none`, but they have `object` elsewhere). Fixes #1703 Fixes #830 Fixes #928
This commit is contained in:
@@ -187,8 +187,8 @@ Val* Compiler::compile_cond(const goos::Object& form, const goos::Object& rest,
|
||||
std::vector<TypeSpec> case_result_types;
|
||||
|
||||
for_each_in_list(rest, [&](const goos::Object& o) {
|
||||
auto test = pair_car(o);
|
||||
auto clauses = pair_cdr(o);
|
||||
const auto& test = pair_car(o);
|
||||
const auto& clauses = pair_cdr(o);
|
||||
|
||||
if (got_else) {
|
||||
throw_compiler_error(form, "Cond from cannot have any cases after else.");
|
||||
@@ -228,12 +228,14 @@ Val* Compiler::compile_cond(const goos::Object& form, const goos::Object& rest,
|
||||
|
||||
// CODE
|
||||
Val* case_result = get_none();
|
||||
const goos::Object* case_clause = nullptr;
|
||||
for_each_in_list(clauses, [&](const goos::Object& clause) {
|
||||
case_result = compile_error_guard(clause, env);
|
||||
if (!dynamic_cast<None*>(case_result)) {
|
||||
case_result = case_result->to_reg(clause, env);
|
||||
}
|
||||
case_clause = &clause;
|
||||
});
|
||||
if (case_clause && !dynamic_cast<None*>(case_result)) {
|
||||
case_result = case_result->to_reg(*case_clause, env);
|
||||
}
|
||||
|
||||
case_result_types.push_back(case_result->type());
|
||||
if (!is_none(case_result)) {
|
||||
@@ -251,15 +253,24 @@ Val* Compiler::compile_cond(const goos::Object& form, const goos::Object& rest,
|
||||
});
|
||||
|
||||
if (!got_else) {
|
||||
// if no else, clause, return #f. But don't retype. todo what does goal do here?
|
||||
// if no else clause, return #f.
|
||||
auto get_false = std::make_unique<IR_LoadSymbolPointer>(result, "#f");
|
||||
env->emit(form, std::move(get_false));
|
||||
}
|
||||
|
||||
if (case_result_types.empty()) {
|
||||
// completely empty cond
|
||||
result->set_type(TypeSpec("none"));
|
||||
} else {
|
||||
result->set_type(coerce_to_reg_type(m_ts.lowest_common_ancestor(case_result_types)));
|
||||
auto lca = m_ts.lowest_common_ancestor(case_result_types);
|
||||
if (!got_else && lca == TypeSpec("none")) {
|
||||
// least common ancestor was none, but there is still the #f from the missing else case.
|
||||
// elevate cond to an `object` overall so we can capture that #f!
|
||||
// (`object` is the direct ancestor of `none` and the ancestor to all types overall)
|
||||
// TODO : what does goal do here?
|
||||
lca = TypeSpec("object");
|
||||
}
|
||||
result->set_type(coerce_to_reg_type(lca));
|
||||
}
|
||||
|
||||
// maybe use 128-bit register
|
||||
|
||||
Reference in New Issue
Block a user