From 286be582cbf1f45c069e2d8ea5156210fd716b0c Mon Sep 17 00:00:00 2001 From: water Date: Fri, 29 Apr 2022 20:04:37 -0400 Subject: [PATCH] one possible approach to multiple threads using the compiler --- goalc/compiler/Compiler.cpp | 146 +++++++++++++++++------------------- goalc/compiler/Compiler.h | 5 +- goalc/main.cpp | 49 +++++++++++- 3 files changed, 118 insertions(+), 82 deletions(-) diff --git a/goalc/compiler/Compiler.cpp b/goalc/compiler/Compiler.cpp index 374155ce80..bba333ffe4 100644 --- a/goalc/compiler/Compiler.cpp +++ b/goalc/compiler/Compiler.cpp @@ -44,90 +44,75 @@ Compiler::Compiler(const std::string& user_profile, std::unique_ptr // 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 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) { diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index b8939f2842..75fa4fc58a 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -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 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 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 m_global_env = nullptr; diff --git a/goalc/main.cpp b/goalc/main.cpp index ff395afb24..86888768c2 100644 --- a/goalc/main.cpp +++ b/goalc/main.cpp @@ -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; + 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 lock(compiler_mutex); + // status = compiler->handle_repl_string(msg); + // } + // } + // }); + ReplStatus status = ReplStatus::WANT_RELOAD; - while (status == ReplStatus::WANT_RELOAD) { - compiler = std::make_unique(username, std::make_unique()); - 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 lock(compiler_mutex); + compiler = std::make_unique(username, std::make_unique()); + status = ReplStatus::OK; + } + + std::string input_from_stdin = compiler->get_repl_input(); + if (!input_from_stdin.empty()) { + // lock, while we compile + std::lock_guard lock(compiler_mutex); + status = compiler->handle_repl_string(input_from_stdin); + } + + if (!auto_input.empty()) { + // lock, while we compile + std::lock_guard lock(compiler_mutex); + status = compiler->handle_repl_string(auto_input); + auto_input.clear(); } } + + // server_thread.join(); } else { compiler = std::make_unique(); compiler->run_front_end_on_string(argument);