one possible approach to multiple threads using the compiler

This commit is contained in:
water
2022-04-29 20:04:37 -04:00
parent f9313d8260
commit 286be582cb
3 changed files with 118 additions and 82 deletions
+69 -77
View File
@@ -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) {
+4 -1
View File
@@ -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
View File
@@ -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);