diff --git a/goalc/compiler/Compiler.cpp b/goalc/compiler/Compiler.cpp index 26377e1ef4..b828976811 100644 --- a/goalc/compiler/Compiler.cpp +++ b/goalc/compiler/Compiler.cpp @@ -14,9 +14,7 @@ using namespace goos; -Compiler::Compiler(const int nrepl_port, - const std::string& user_profile, - std::unique_ptr repl) +Compiler::Compiler(const std::string& user_profile, std::unique_ptr repl) : m_goos(user_profile), m_debugger(&m_listener, &m_goos.reader), m_repl(std::move(repl)) { m_listener.add_debugger(&m_debugger); m_ts.add_builtin_types(); @@ -48,38 +46,33 @@ Compiler::Compiler(const int nrepl_port, // 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(); +} - m_nrepl_port = nrepl_port; - fmt::print("[nREPL]: Server Will Listen for a Connection on Port {}!\n\r", m_nrepl_port); - nrepl_thread = std::thread([&]() { - asio::io_context io_context; - ReplServer s(io_context, this); - try { - io_context.run(); - } catch (std::exception& e) { - print_compiler_warning("Could not setup nREPL {}\n", e.what()); - } - }); +void Compiler::lock() { + compiler_mutex.lock(); +} + +void Compiler::unlock() { + compiler_mutex.unlock(); } 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))); - if (auto_debug || auto_listen) { read_eval_print("(lt)"); } diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index b74a207ba2..a974936529 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -20,6 +20,7 @@ #include "goalc/make/MakeSystem.h" #include "goalc/data_compiler/game_text.h" #include "goalc/data_compiler/game_subtitle.h" +#include enum MathMode { MATH_INT, MATH_BINT, MATH_FLOAT, MATH_INVALID }; @@ -27,9 +28,7 @@ enum class ReplStatus { OK, WANT_EXIT, WANT_RELOAD }; class Compiler { public: - Compiler(const int nrepl_port = 8181, - const std::string& user_profile = "#f", - std::unique_ptr repl = nullptr); + Compiler(const std::string& user_profile = "#f", std::unique_ptr repl = nullptr); void read_eval_print(std::string input = ""); ReplStatus execute_repl(bool auto_listen = false, bool auto_debug = false); goos::Interpreter& get_goos() { return m_goos; } @@ -72,8 +71,8 @@ class Compiler { std::vector> const& user_data); bool knows_object_file(const std::string& name); MakeSystem& make_system() { return m_make; } - - int m_nrepl_port; + void lock(); + void unlock(); private: TypeSystem m_ts; @@ -93,8 +92,7 @@ class Compiler { SymbolInfoMap m_symbol_info; std::unique_ptr m_repl; MakeSystem m_make; - - std::thread nrepl_thread; + std::mutex compiler_mutex; struct DebugStats { int num_spills = 0; diff --git a/goalc/main.cpp b/goalc/main.cpp index c788fa4d8e..e0cf627213 100644 --- a/goalc/main.cpp +++ b/goalc/main.cpp @@ -10,6 +10,7 @@ #include "common/goos/ReplUtils.h" #include +#include void setup_logging(bool verbose) { lg::set_file(file_util::get_file_path({"log/compiler.txt"})); @@ -64,11 +65,10 @@ int main(int argc, char** argv) { std::string found_username; while (ts.text_remains()) { auto character = std::string(1, ts.read()); - if (std::regex_match(character, allowed_chars)) { - found_username.push_back(ts.read()); - } else { + if (!std::regex_match(character, allowed_chars)) { break; } + found_username.push_back(ts.read()); } if (!found_username.empty()) { username = found_username; @@ -83,26 +83,52 @@ int main(int argc, char** argv) { lg::info("OpenGOAL Compiler {}.{}", versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR); // Init REPL + ReplStatus status = ReplStatus::WANT_RELOAD; + std::function shutdown_callback = [&]() { return status == ReplStatus::WANT_EXIT; }; + ReplServer repl_server(shutdown_callback, nrepl_port); + bool repl_server_ok = repl_server.init_server(); + if (repl_server_ok) { + fmt::print("[nREPL] Will wait for a connection on port {}\n", nrepl_port); + } + std::thread nrepl_thread; // the compiler may throw an exception if it fails to load its standard library. try { - std::unique_ptr compiler; + std::shared_ptr compiler; + // if a command is provided on the command line, no REPL just run the compiler on it if (!cmd.empty()) { - compiler = std::make_unique(); + compiler = std::make_shared(); compiler->run_front_end_on_string(cmd); - } else { - ReplStatus status = ReplStatus::WANT_RELOAD; - while (status == ReplStatus::WANT_RELOAD) { - compiler = - std::make_unique(nrepl_port, username, std::make_unique()); - status = compiler->execute_repl(auto_listen, auto_debug); - if (status == ReplStatus::WANT_RELOAD) { - fmt::print("Reloading compiler...\n"); + return 0; + } + // Otherwise, run the REPL and such + compiler = std::make_shared(username, std::make_unique()); + // Start nREPL Server + if (repl_server_ok) { + nrepl_thread = std::thread([&]() { + while (!shutdown_callback()) { + if (repl_server.wait_for_connection()) { + repl_server.read_data(); + } else { + std::this_thread::sleep_for(std::chrono::microseconds(50000)); + } } + }); + } + // Poll Terminal + while (status == ReplStatus::WANT_RELOAD) { + status = compiler->execute_repl(auto_listen, auto_debug); + if (status == ReplStatus::WANT_RELOAD) { + fmt::print("Reloading compiler...\n"); } } } catch (std::exception& e) { - fmt::print("Compiler Fatal Error: {}\n", e.what()); + fmt::print(stderr, "Compiler Fatal Error: {}\n", e.what()); } + // Cleanup + if (repl_server_ok) { + repl_server.shutdown_server(); + nrepl_thread.join(); + } return 0; } diff --git a/scripts/nrepl-test.py b/scripts/nrepl-test.py new file mode 100644 index 0000000000..4fa431c640 --- /dev/null +++ b/scripts/nrepl-test.py @@ -0,0 +1,6 @@ +import socket +clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM); +clientSocket.connect(("127.0.0.1", 8181)) +print(clientSocket) +num_sent = clientSocket.send(b'\x01\x02\x03\x04') +print("Sent {} bytes".format(num_sent))