mirror of
https://github.com/open-goal/jak-project
synced 2026-09-10 12:25:21 -04:00
one possible approach to multiple threads using the compiler
This commit is contained in:
+69
-77
@@ -44,90 +44,75 @@ Compiler::Compiler(const std::string& user_profile, std::unique_ptr<ReplWrapper>
|
||||
// load auto-complete history, only if we are running in the interactive mode.
|
||||
if (m_repl) {
|
||||
m_repl->load_history();
|
||||
// init repl
|
||||
m_repl->print_welcome_message();
|
||||
auto examples = m_repl->examples;
|
||||
auto regex_colors = m_repl->regex_colors;
|
||||
m_repl->init_default_settings();
|
||||
using namespace std::placeholders;
|
||||
m_repl->get_repl().set_completion_callback(
|
||||
std::bind(&Compiler::find_symbols_by_prefix, this, _1, _2, std::cref(examples)));
|
||||
m_repl->get_repl().set_hint_callback(
|
||||
std::bind(&Compiler::find_hints_by_prefix, this, _1, _2, _3, std::cref(examples)));
|
||||
m_repl->get_repl().set_highlighter_callback(
|
||||
std::bind(&Compiler::repl_coloring, this, _1, _2, std::cref(regex_colors)));
|
||||
}
|
||||
|
||||
// add GOOS forms that get info from the compiler
|
||||
setup_goos_forms();
|
||||
}
|
||||
|
||||
ReplStatus Compiler::execute_repl(bool auto_listen, bool auto_debug) {
|
||||
// init repl
|
||||
m_repl->print_welcome_message();
|
||||
auto examples = m_repl->examples;
|
||||
auto regex_colors = m_repl->regex_colors;
|
||||
m_repl->init_default_settings();
|
||||
using namespace std::placeholders;
|
||||
m_repl->get_repl().set_completion_callback(
|
||||
std::bind(&Compiler::find_symbols_by_prefix, this, _1, _2, std::cref(examples)));
|
||||
m_repl->get_repl().set_hint_callback(
|
||||
std::bind(&Compiler::find_hints_by_prefix, this, _1, _2, _3, std::cref(examples)));
|
||||
m_repl->get_repl().set_highlighter_callback(
|
||||
std::bind(&Compiler::repl_coloring, this, _1, _2, std::cref(regex_colors)));
|
||||
|
||||
std::string auto_input;
|
||||
if (auto_debug || auto_listen) {
|
||||
auto_input.append("(lt)");
|
||||
}
|
||||
if (auto_debug) {
|
||||
auto_input.append("(dbg) (:cont)");
|
||||
}
|
||||
|
||||
while (!m_want_exit && !m_want_reload) {
|
||||
try {
|
||||
std::optional<goos::Object> code;
|
||||
|
||||
if (auto_input.empty()) {
|
||||
// 1). get a line from the user (READ)
|
||||
std::string prompt = fmt::format(fmt::emphasis::bold | fg(fmt::color::cyan), "g > ");
|
||||
if (m_listener.is_connected()) {
|
||||
prompt = fmt::format(fmt::emphasis::bold | fg(fmt::color::lime_green), "gc> ");
|
||||
}
|
||||
if (m_debugger.is_halted()) {
|
||||
prompt = fmt::format(fmt::emphasis::bold | fg(fmt::color::magenta), "gs> ");
|
||||
} else if (m_debugger.is_attached()) {
|
||||
prompt = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), "gr> ");
|
||||
}
|
||||
|
||||
code = m_goos.reader.read_from_stdin(prompt, *m_repl);
|
||||
} else {
|
||||
code = m_goos.reader.read_from_string(auto_input);
|
||||
auto_input.clear();
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2). compile
|
||||
auto obj_file = compile_object_file("repl", *code, m_listener.is_connected());
|
||||
if (m_settings.debug_print_ir) {
|
||||
obj_file->debug_print_tl();
|
||||
}
|
||||
|
||||
if (!obj_file->is_empty()) {
|
||||
// 3). color
|
||||
color_object_file(obj_file);
|
||||
|
||||
// 4). codegen
|
||||
auto data = codegen_object_file(obj_file);
|
||||
|
||||
// 4). send!
|
||||
if (m_listener.is_connected()) {
|
||||
m_listener.send_code(data);
|
||||
if (!m_listener.most_recent_send_was_acked()) {
|
||||
print_compiler_warning("Runtime is not responding. Did it crash?\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (std::exception& e) {
|
||||
print_compiler_warning("REPL Error: {}\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string Compiler::get_repl_input() {
|
||||
std::string prompt = fmt::format(fmt::emphasis::bold | fg(fmt::color::cyan), "g > ");
|
||||
if (m_listener.is_connected()) {
|
||||
m_listener.send_reset(false); // reset the target
|
||||
m_listener.disconnect();
|
||||
prompt = fmt::format(fmt::emphasis::bold | fg(fmt::color::lime_green), "gc> ");
|
||||
}
|
||||
if (m_debugger.is_halted()) {
|
||||
prompt = fmt::format(fmt::emphasis::bold | fg(fmt::color::magenta), "gs> ");
|
||||
} else if (m_debugger.is_attached()) {
|
||||
prompt = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), "gr> ");
|
||||
}
|
||||
|
||||
std::string prompt_full = "\033[0m" + prompt;
|
||||
auto str = m_repl->readline(prompt_full);
|
||||
if (str) {
|
||||
return str;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
ReplStatus Compiler::handle_repl_string(const std::string& str) {
|
||||
if (str.empty()) {
|
||||
return ReplStatus::OK;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1). read
|
||||
goos::Object code = m_goos.reader.read_from_string(str, true, "REPL");
|
||||
// 2). compile
|
||||
auto obj_file = compile_object_file("repl", code, m_listener.is_connected());
|
||||
if (m_settings.debug_print_ir) {
|
||||
obj_file->debug_print_tl();
|
||||
}
|
||||
|
||||
if (!obj_file->is_empty()) {
|
||||
// 3). color
|
||||
color_object_file(obj_file);
|
||||
|
||||
// 4). codegen
|
||||
auto data = codegen_object_file(obj_file);
|
||||
|
||||
// 4). send!
|
||||
if (m_listener.is_connected()) {
|
||||
m_listener.send_code(data);
|
||||
if (!m_listener.most_recent_send_was_acked()) {
|
||||
print_compiler_warning("Runtime is not responding. Did it crash?\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
print_compiler_warning("REPL Error: {}\n", e.what());
|
||||
}
|
||||
|
||||
if (m_want_exit) {
|
||||
@@ -141,6 +126,13 @@ ReplStatus Compiler::execute_repl(bool auto_listen, bool auto_debug) {
|
||||
return ReplStatus::OK;
|
||||
}
|
||||
|
||||
Compiler::~Compiler() {
|
||||
if (m_listener.is_connected()) {
|
||||
m_listener.send_reset(false); // reset the target
|
||||
m_listener.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
FileEnv* Compiler::compile_object_file(const std::string& name,
|
||||
goos::Object code,
|
||||
bool allow_emit) {
|
||||
|
||||
@@ -27,7 +27,7 @@ enum class ReplStatus { OK, WANT_EXIT, WANT_RELOAD };
|
||||
class Compiler {
|
||||
public:
|
||||
Compiler(const std::string& user_profile = "#f", std::unique_ptr<ReplWrapper> repl = nullptr);
|
||||
ReplStatus execute_repl(bool auto_listen = false, bool auto_debug = false);
|
||||
~Compiler();
|
||||
goos::Interpreter& get_goos() { return m_goos; }
|
||||
FileEnv* compile_object_file(const std::string& name, goos::Object code, bool allow_emit);
|
||||
std::unique_ptr<FunctionEnv> compile_top_level_function(const std::string& name,
|
||||
@@ -69,6 +69,9 @@ class Compiler {
|
||||
bool knows_object_file(const std::string& name);
|
||||
MakeSystem& make_system() { return m_make; }
|
||||
|
||||
std::string get_repl_input();
|
||||
ReplStatus handle_repl_string(const std::string& str);
|
||||
|
||||
private:
|
||||
TypeSystem m_ts;
|
||||
std::unique_ptr<GlobalEnv> m_global_env = nullptr;
|
||||
|
||||
+45
-4
@@ -74,19 +74,60 @@ int main(int argc, char** argv) {
|
||||
|
||||
lg::info("OpenGOAL Compiler {}.{}", versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR);
|
||||
|
||||
std::string auto_input;
|
||||
if (auto_debug || auto_listen) {
|
||||
auto_input.append("(lt)");
|
||||
}
|
||||
if (auto_debug) {
|
||||
auto_input.append("(dbg) (:cont)");
|
||||
}
|
||||
|
||||
// Init REPL
|
||||
// the compiler may throw an exception if it fails to load its standard library.
|
||||
try {
|
||||
std::unique_ptr<Compiler> compiler;
|
||||
std::mutex compiler_mutex;
|
||||
if (argument.empty()) {
|
||||
|
||||
// for example, start a separate thread
|
||||
// std::thread server_thread([&](){
|
||||
// while (!want_exit) {
|
||||
// std::string msg = server.get_msg();
|
||||
// {
|
||||
// // only locked inside this scope
|
||||
// std::lock_guard<std::mutex> lock(compiler_mutex);
|
||||
// status = compiler->handle_repl_string(msg);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
ReplStatus status = ReplStatus::WANT_RELOAD;
|
||||
while (status == ReplStatus::WANT_RELOAD) {
|
||||
compiler = std::make_unique<Compiler>(username, std::make_unique<ReplWrapper>());
|
||||
status = compiler->execute_repl(auto_listen, auto_debug);
|
||||
// loop, until the user requests an exit
|
||||
while (status != ReplStatus::WANT_EXIT) {
|
||||
// if we want to reload the compiler, reconstruct it
|
||||
if (status == ReplStatus::WANT_RELOAD) {
|
||||
fmt::print("Reloading compiler...\n");
|
||||
// lock, in case something else is using it
|
||||
std::lock_guard<std::mutex> lock(compiler_mutex);
|
||||
compiler = std::make_unique<Compiler>(username, std::make_unique<ReplWrapper>());
|
||||
status = ReplStatus::OK;
|
||||
}
|
||||
|
||||
std::string input_from_stdin = compiler->get_repl_input();
|
||||
if (!input_from_stdin.empty()) {
|
||||
// lock, while we compile
|
||||
std::lock_guard<std::mutex> lock(compiler_mutex);
|
||||
status = compiler->handle_repl_string(input_from_stdin);
|
||||
}
|
||||
|
||||
if (!auto_input.empty()) {
|
||||
// lock, while we compile
|
||||
std::lock_guard<std::mutex> lock(compiler_mutex);
|
||||
status = compiler->handle_repl_string(auto_input);
|
||||
auto_input.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// server_thread.join();
|
||||
} else {
|
||||
compiler = std::make_unique<Compiler>();
|
||||
compiler->run_front_end_on_string(argument);
|
||||
|
||||
Reference in New Issue
Block a user