mirror of
https://github.com/open-goal/jak-project
synced 2026-08-18 13:53:01 -04:00
@@ -1,4 +1,5 @@
|
||||
#include "state.h"
|
||||
#include "common/type_system/TypeSystem.h"
|
||||
|
||||
/*!
|
||||
* Convert a (state <blah> ...) to the function required to go. Must be state.
|
||||
@@ -81,4 +82,51 @@ TypeSpec get_state_handler_type(StateHandler kind, const TypeSpec& state_type) {
|
||||
}
|
||||
result.add_or_modify_tag("behavior", state_type.last_arg().base_type());
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
TypeSpec func_to_state_type(const TypeSpec& func_type, const TypeSpec& proc_type) {
|
||||
TypeSpec result("state");
|
||||
for (int i = 0; i < ((int)func_type.arg_count()) - 1; i++) {
|
||||
result.add_arg(func_type.get_arg(i));
|
||||
}
|
||||
result.add_arg(proc_type);
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::optional<TypeSpec> get_state_type_from_enter_and_code(const TypeSpec& enter_func_type,
|
||||
const TypeSpec& code_func_type,
|
||||
const TypeSpec& proc_type,
|
||||
const TypeSystem& ts) {
|
||||
bool enter_real_func =
|
||||
enter_func_type.base_type() == "function" && enter_func_type.arg_count() > 0;
|
||||
bool code_real_func = code_func_type.base_type() == "function" && code_func_type.arg_count() > 0;
|
||||
|
||||
if (enter_real_func && code_real_func) {
|
||||
int i = 0;
|
||||
TypeSpec result("state");
|
||||
for (; i < std::min((int)enter_func_type.arg_count(), (int)code_func_type.arg_count()) - 1;
|
||||
i++) {
|
||||
result.add_arg(
|
||||
ts.lowest_common_ancestor(enter_func_type.get_arg(i), code_func_type.get_arg(i)));
|
||||
}
|
||||
|
||||
for (; i < ((int)enter_func_type.arg_count()) - 1; i++) {
|
||||
result.add_arg(enter_func_type.get_arg(i));
|
||||
}
|
||||
|
||||
for (; i < ((int)code_func_type.arg_count()) - 1; i++) {
|
||||
result.add_arg(code_func_type.get_arg(i));
|
||||
}
|
||||
|
||||
result.add_arg(proc_type);
|
||||
return result;
|
||||
} else if (enter_real_func) {
|
||||
return func_to_state_type(enter_func_type, proc_type);
|
||||
} else if (code_real_func) {
|
||||
return func_to_state_type(code_func_type, proc_type);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include "common/type_system/TypeSpec.h"
|
||||
|
||||
/*!
|
||||
@@ -8,8 +9,15 @@
|
||||
|
||||
enum class StateHandler { ENTER, EXIT, CODE, TRANS, POST, EVENT };
|
||||
|
||||
class TypeSystem;
|
||||
|
||||
TypeSpec state_to_go_function(const TypeSpec& state_type);
|
||||
StateHandler handler_name_to_kind(const std::string& name);
|
||||
std::string handler_kind_to_name(StateHandler kind);
|
||||
TypeSpec get_state_handler_type(const std::string& handler_name, const TypeSpec& state_type);
|
||||
TypeSpec get_state_handler_type(StateHandler kind, const TypeSpec& state_type);
|
||||
TypeSpec get_state_handler_type(StateHandler kind, const TypeSpec& state_type);
|
||||
|
||||
std::optional<TypeSpec> get_state_type_from_enter_and_code(const TypeSpec& enter_func_type,
|
||||
const TypeSpec& code_func_type,
|
||||
const TypeSpec& proc_type,
|
||||
const TypeSystem& ts);
|
||||
@@ -2700,9 +2700,18 @@ void FunctionCallElement::update_from_stack(const Env& env,
|
||||
std::swap(all_pop_vars.at(0), all_pop_vars.at(1));
|
||||
}
|
||||
|
||||
if (tp_type.kind == TP_Type::Kind::RUN_FUNCTION_IN_PROCESS_FUNCTION &&
|
||||
unstacked.at(0)->to_string(env) == "run-function-in-process") {
|
||||
unstacked.at(0) = pool.form<ConstantTokenElement>("run-now-in-process");
|
||||
if (tp_type.kind == TP_Type::Kind::RUN_FUNCTION_IN_PROCESS_FUNCTION) {
|
||||
if (unstacked.at(0)->to_string(env) == "run-function-in-process") {
|
||||
unstacked.at(0) = pool.form<ConstantTokenElement>("run-now-in-process");
|
||||
} else {
|
||||
// couldn't pop. need to add a cast.
|
||||
TypeSpec failed_cast("function");
|
||||
for (int i = 0; i < ((int)unstacked.size()) - 1; i++) {
|
||||
failed_cast.add_arg(TypeSpec("object"));
|
||||
}
|
||||
failed_cast.add_arg(TypeSpec("none"));
|
||||
unstacked.at(0) = pool.form<CastElement>(failed_cast, unstacked.at(0));
|
||||
}
|
||||
}
|
||||
|
||||
if (tp_type.kind == TP_Type::Kind::SET_TO_RUN_FUNCTION) {
|
||||
|
||||
+8
-1
@@ -26,7 +26,14 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
// collect all files to process
|
||||
auto config = read_config_file(argv[1]);
|
||||
Config config;
|
||||
try {
|
||||
config = read_config_file(argv[1]);
|
||||
} catch (const std::exception& e) {
|
||||
lg::error("Failed to parse config");
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string in_folder = argv[2];
|
||||
std::string out_folder = argv[3];
|
||||
|
||||
|
||||
@@ -60,20 +60,33 @@ Val* Compiler::compile_define_state_hook(const goos::Object& form,
|
||||
do_set(form, code_field, code_value->to_gpr(form, env), code_value, env);
|
||||
|
||||
// state name
|
||||
TypeSpec state_type("state");
|
||||
auto state_type = get_state_type_from_enter_and_code(enter_value->type(), code_value->type(),
|
||||
state_parent_type, m_ts);
|
||||
|
||||
for (int i = 0; i < (int)code_value->type().arg_count() - 1; i++) {
|
||||
state_type.add_arg(code_value->type().get_arg(i));
|
||||
}
|
||||
state_type.add_arg(state_parent_type);
|
||||
auto state_name = args.unnamed.at(0).as_symbol()->name;
|
||||
auto existing_var = m_symbol_types.find(state_name);
|
||||
if (existing_var != m_symbol_types.end() && existing_var->second != state_type) {
|
||||
throw_compiler_error(form, "define-state would redefine the type of symbol {} from {} to {}",
|
||||
state_name, existing_var->second.print(), state_type.print());
|
||||
|
||||
TypeSpec type_to_use;
|
||||
if (existing_var == m_symbol_types.end()) {
|
||||
// we're a new state. we must have a type.
|
||||
if (!state_type) {
|
||||
throw_compiler_error(form,
|
||||
"define-state doesn't have enough information to determine the type of "
|
||||
"state {}, and it was not forward declared.",
|
||||
state_name);
|
||||
}
|
||||
type_to_use = *state_type;
|
||||
m_symbol_types[state_name] = *state_type;
|
||||
} else {
|
||||
type_to_use = existing_var->second;
|
||||
if (state_type) {
|
||||
typecheck(form, existing_var->second, *state_type,
|
||||
fmt::format("type of state {}", state_name));
|
||||
}
|
||||
}
|
||||
m_symbol_types[state_name] = state_type;
|
||||
auto sym_val = env->function_env()->alloc_val<SymbolVal>(state_name, state_type);
|
||||
|
||||
auto sym_val = env->function_env()->alloc_val<SymbolVal>(state_name, type_to_use);
|
||||
|
||||
env->emit_ir<IR_SetSymbolValue>(form, sym_val, state_object);
|
||||
|
||||
return get_none();
|
||||
|
||||
+17
-2
@@ -476,7 +476,10 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(s2-1
|
||||
((the-as
|
||||
(function object object object object object object object object none)
|
||||
s2-1
|
||||
)
|
||||
s1-0
|
||||
s0-0
|
||||
(the-as sparticle-launch-group s3-0)
|
||||
@@ -577,7 +580,19 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(s2-3 s1-2 s0-2 s3-0 sv-224 sv-240 sv-256 sv-272 t3-1)
|
||||
((the-as
|
||||
(function object object object object object object object object none)
|
||||
s2-3
|
||||
)
|
||||
s1-2
|
||||
s0-2
|
||||
s3-0
|
||||
sv-224
|
||||
sv-240
|
||||
sv-256
|
||||
sv-272
|
||||
t3-1
|
||||
)
|
||||
)
|
||||
)
|
||||
(-> s4-3 ppointer)
|
||||
|
||||
@@ -293,7 +293,7 @@ CompareResult compare(Decompiler& dc, const std::vector<DecompilerFile>& refs, b
|
||||
compare_result.failing_files.push_back(file.unique_name);
|
||||
compare_result.total_pass = false;
|
||||
fmt::print("Reference test failure on {}:\n", file.unique_name);
|
||||
fmt::print("{}\n", diff_strings(result, ref));
|
||||
fmt::print("{}\n", diff_strings(ref, result));
|
||||
|
||||
if (dump_mode) {
|
||||
file_util::create_dir_if_needed("./failures");
|
||||
|
||||
Reference in New Issue
Block a user