From 705e80ad6b573fd9f4a3c1f15047884049e62e2f Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sun, 19 Nov 2023 21:50:52 +0100 Subject: [PATCH] Everywhere: Split REPL from main(), put settings in environment --- src/ast.cpp | 9 ++- src/env/environment.cpp | 15 +++-- src/env/environment.h | 6 +- src/env/functions/collection-modify.cpp | 5 +- src/env/functions/mutable.cpp | 3 +- src/env/functions/repl.cpp | 7 +- src/eval-special-form.cpp | 2 +- src/eval.h | 3 +- src/forward.h | 10 ++- src/main.cpp | 84 +++++++++++++++++++++++ src/printer.cpp | 2 +- src/reader.cpp | 8 +-- src/repl.cpp | 89 +++++-------------------- src/repl.h | 29 ++++++++ src/settings.cpp | 13 ++++ src/settings.h | 8 +-- 16 files changed, 186 insertions(+), 107 deletions(-) create mode 100644 src/main.cpp create mode 100644 src/repl.h diff --git a/src/ast.cpp b/src/ast.cpp index d92e693..94e46d3 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -226,7 +226,8 @@ Callable::Callable(ValuePtr meta) // ----------------------------------------- Function::Function(std::string_view name, std::string_view bindings, std::string_view documentation, FunctionType function) - : m_name(name) + : Callable() + , m_name(name) , m_bindings(bindings) , m_documentation(documentation) , m_function(function) @@ -243,14 +244,16 @@ Function::Function(const Function& that, ValuePtr meta) // ----------------------------------------- Lambda::Lambda(const std::vector& bindings, ValuePtr body, EnvironmentPtr env) - : m_bindings(bindings) + : Callable() + , m_bindings(bindings) , m_body(body) , m_env(env) { } Lambda::Lambda(const Lambda& that) - : m_bindings(that.m_bindings) + : Callable() + , m_bindings(that.m_bindings) , m_body(that.m_body) , m_env(that.m_env) { diff --git a/src/env/environment.cpp b/src/env/environment.cpp index ba46f52..eb46d91 100644 --- a/src/env/environment.cpp +++ b/src/env/environment.cpp @@ -15,6 +15,7 @@ #include "env/environment.h" #include "error.h" #include "forward.h" +#include "repl.h" namespace blaze { @@ -135,21 +136,21 @@ void Environment::installFunctions(EnvironmentPtr env) } for (const auto& lambda : s_lambdas) { // Ensure all s-exprs are run with (do) - eval(read("(do " + lambda + ")"), env); + Repl::eval(Repl::read("(do " + lambda + ")"), env); } } // ----------------------------------------- -bool Environment::exists(const std::string& symbol) +bool Environment::exists(std::string_view symbol) { - return m_values.find(symbol) != m_values.end(); + return m_values.find(std::string(symbol)) != m_values.end(); } -ValuePtr Environment::set(const std::string& symbol, ValuePtr value) +ValuePtr Environment::set(std::string_view symbol, ValuePtr value) { if (exists(symbol)) { - m_values.erase(symbol); + m_values.erase(std::string(symbol)); } m_values.emplace(symbol, value); @@ -157,10 +158,10 @@ ValuePtr Environment::set(const std::string& symbol, ValuePtr value) return value; } -ValuePtr Environment::get(const std::string& symbol) +ValuePtr Environment::get(std::string_view symbol) { if (exists(symbol)) { - return m_values[symbol]; + return m_values[std::string(symbol)]; } if (m_outer) { diff --git a/src/env/environment.h b/src/env/environment.h index ac7c93b..b24058a 100644 --- a/src/env/environment.h +++ b/src/env/environment.h @@ -37,9 +37,9 @@ public: static void registerFunction(FunctionParts function_parts); static void installFunctions(EnvironmentPtr env); - bool exists(const std::string& symbol); - ValuePtr set(const std::string& symbol, ValuePtr value); - ValuePtr get(const std::string& symbol); + bool exists(std::string_view symbol); + ValuePtr set(std::string_view symbol, ValuePtr value); + ValuePtr get(std::string_view symbol); private: Environment() {} diff --git a/src/env/functions/collection-modify.cpp b/src/env/functions/collection-modify.cpp index c68252d..54bc098 100644 --- a/src/env/functions/collection-modify.cpp +++ b/src/env/functions/collection-modify.cpp @@ -12,6 +12,7 @@ #include "env/environment.h" #include "env/macro.h" #include "forward.h" +#include "repl.h" #include "util.h" namespace blaze { @@ -47,7 +48,7 @@ void Environment::loadCollectionModify() } else { auto lambda = std::static_pointer_cast(callable); - value = eval(lambda->body(), Environment::create(lambda, std::move(arguments))); + value = Repl::eval(lambda->body(), Environment::create(lambda, std::move(arguments))); } return value; @@ -152,7 +153,7 @@ void Environment::loadCollectionModify() auto lambda = std::static_pointer_cast(callable); auto collection_nodes = collection->nodesRead(); for (size_t i = 0; i < count; ++i) { - nodes.at(i) = (eval(lambda->body(), Environment::create(lambda, { collection_nodes[i] }))); + nodes.at(i) = (Repl::eval(lambda->body(), Environment::create(lambda, { collection_nodes[i] }))); } } diff --git a/src/env/functions/mutable.cpp b/src/env/functions/mutable.cpp index 4d691dc..9e1c11c 100644 --- a/src/env/functions/mutable.cpp +++ b/src/env/functions/mutable.cpp @@ -11,6 +11,7 @@ #include "env/environment.h" #include "env/macro.h" #include "forward.h" +#include "repl.h" #include "util.h" namespace blaze { @@ -82,7 +83,7 @@ void Environment::loadMutable() } else { auto lambda = std::static_pointer_cast(callable); - value = eval(lambda->body(), Environment::create(lambda, std::move(arguments))); + value = Repl::eval(lambda->body(), Environment::create(lambda, std::move(arguments))); } return atom->reset(value); diff --git a/src/env/functions/repl.cpp b/src/env/functions/repl.cpp index 92640a9..469bd24 100644 --- a/src/env/functions/repl.cpp +++ b/src/env/functions/repl.cpp @@ -10,6 +10,7 @@ #include "ast.h" #include "env/macro.h" +#include "repl.h" #include "util.h" namespace blaze { @@ -27,7 +28,7 @@ void Environment::loadRepl() VALUE_CAST(node, String, (*begin)); std::string input = node->data(); - return read(input); + return Repl::read(input); }); // Read file contents @@ -56,7 +57,7 @@ void Environment::loadRepl() VALUE_CAST(prompt, String, (*begin)); - return readline(prompt->data()); + return Repl::readline(prompt->data()); }); // REPL eval @@ -67,7 +68,7 @@ void Environment::loadRepl() { CHECK_ARG_COUNT_IS("eval", SIZE(), 1); - return eval(*begin, nullptr); + return Repl::eval(*begin, nullptr); }); } diff --git a/src/eval-special-form.cpp b/src/eval-special-form.cpp index 15d20ae..2d33735 100644 --- a/src/eval-special-form.cpp +++ b/src/eval-special-form.cpp @@ -96,7 +96,7 @@ ValuePtr Eval::evalDescribe(const ValueVector& nodes, EnvironmentPtr env) std::string documentation; std::string value_string; - bool pretty_print = Settings::the().get("pretty-print") == "1"; + bool pretty_print = Settings::the().getEnvBool("*PRETTY-PRINT*"); auto bold = fg(ruc::format::TerminalColor::None) | ruc::format::Emphasis::Bold; auto describe = [&]() { diff --git a/src/eval.h b/src/eval.h index 5a1c79c..cedde0d 100644 --- a/src/eval.h +++ b/src/eval.h @@ -8,8 +8,7 @@ #include -#include "env/environment.h" -#include "forward.h" +#include "forward.h" // EnvironmentPtr namespace blaze { diff --git a/src/forward.h b/src/forward.h index b3f744b..cfc701e 100644 --- a/src/forward.h +++ b/src/forward.h @@ -25,11 +25,15 @@ typedef ValueVector::const_reverse_iterator ValueVectorConstReverseIt; class Environment; typedef std::shared_ptr EnvironmentPtr; +class Readline; + // ----------------------------------------- // Functions -extern ValuePtr readline(const std::string& prompt); -extern ValuePtr read(std::string_view input); -extern ValuePtr eval(ValuePtr ast, EnvironmentPtr env); +// ----------------------------------------- +// Variables + +extern Readline g_readline; +extern EnvironmentPtr g_outer_env; } // namespace blaze diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..b08bc39 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2023 Riyyi + * + * SPDX-License-Identifier: MIT + */ + +#include // std::signal +#include +#include +#include + +#include "ruc/argparser.h" +#include "ruc/format/color.h" +#include "ruc/format/print.h" + +#include "ast.h" +#include "env/environment.h" +#include "forward.h" +#include "repl.h" +#include "settings.h" + +namespace blaze { + +auto main(int argc, char* argv[]) -> int +{ + bool dump_lexer = false; + bool dump_reader = false; + bool pretty_print = false; + std::string_view history_path = "~/.blaze-history"; + std::vector arguments; + + // CLI arguments + ruc::ArgParser arg_parser; + arg_parser.addOption(dump_lexer, 'l', "dump-lexer", nullptr, nullptr); + arg_parser.addOption(dump_reader, 'r', "dump-reader", nullptr, nullptr); + arg_parser.addOption(pretty_print, 'c', "color", nullptr, nullptr); + arg_parser.addOption(history_path, 'h', "history-path", nullptr, nullptr, nullptr, ruc::ArgParser::Required::Yes); + // TODO: Add overload for addArgument(std::vector) + arg_parser.addArgument(arguments, "arguments", nullptr, nullptr, ruc::ArgParser::Required::No); + arg_parser.parse(argc, argv); + + // Set settings + g_outer_env->set("*DUMP-LEXER*", makePtr(dump_lexer)); + g_outer_env->set("*DUMP-READER*", makePtr(dump_reader)); + g_outer_env->set("*PRETTY-PRINT*", makePtr(pretty_print)); + + // Signal callbacks + std::signal(SIGINT, Repl::cleanup); + std::signal(SIGTERM, Repl::cleanup); + + Environment::loadFunctions(); + Environment::installFunctions(g_outer_env); + Repl::makeArgv(g_outer_env, arguments); + + if (arguments.size() > 0) { + Repl::rep(format("(load-file \"{}\")", arguments.front()), g_outer_env); + return 0; + } + + Repl::rep("(println (str \"Blaze [\" *host-language* \"]\"))", g_outer_env); + + g_readline = Readline(pretty_print, history_path); + + std::string input; + while (g_readline.get(input)) { + std::string output = Repl::rep(input, g_outer_env); + if (output.length() > 0) { + print("{}\n", output); + } + } + + if (pretty_print) { + print("\033[0m"); + } + + return 0; +} + +} // namespace blaze + +auto main(int argc, char* argv[]) -> int +{ + return blaze::main(argc, argv); +} diff --git a/src/printer.cpp b/src/printer.cpp index 1b3c691..130a395 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -66,7 +66,7 @@ void Printer::init() void Printer::printImpl(ValuePtr value, bool print_readably) { - bool pretty_print = Settings::the().get("pretty-print") == "1"; + bool pretty_print = Settings::the().getEnvBool("*PRETTY-PRINT*"); auto printSpacing = [this]() -> void { if (!m_first_node && !m_previous_node_is_list) { diff --git a/src/reader.cpp b/src/reader.cpp index f54d192..fdc2bec 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -147,7 +147,7 @@ ValuePtr Reader::readList() nodes.push_back(node); } - if (!consumeSpecific(Token { .type = Token::Type::ParenClose })) { // ) + if (!consumeSpecific(Token { .type = Token::Type::ParenClose, .symbol = "" })) { // ) Error::the().add("expected ')', got EOF"); return nullptr; } @@ -168,7 +168,7 @@ ValuePtr Reader::readVector() nodes.push_back(node); } - if (!consumeSpecific(Token { .type = Token::Type::BracketClose })) { // ] + if (!consumeSpecific(Token { .type = Token::Type::BracketClose, .symbol = "" })) { // ] Error::the().add("expected ']', got EOF"); } @@ -201,7 +201,7 @@ ValuePtr Reader::readHashMap() elements.insert_or_assign(HashMap::getKeyString(key), value); } - if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // } + if (!consumeSpecific(Token { .type = Token::Type::BraceClose, .symbol = "" })) { // } Error::the().add("expected '}', got EOF"); return nullptr; } @@ -378,7 +378,7 @@ void Reader::dumpImpl(ValuePtr node) std::string indentation = std::string(m_indentation * INDENTATION_WIDTH, ' '); print("{}", indentation); - bool pretty_print = Settings::the().get("pretty-print") == "1"; + bool pretty_print = Settings::the().getEnvBool("*PRETTY-PRINT*"); auto blue = fg(ruc::format::TerminalColor::BrightBlue); auto yellow = fg(ruc::format::TerminalColor::Yellow); diff --git a/src/repl.cpp b/src/repl.cpp index b02a3b7..7a2c260 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -4,16 +4,13 @@ * SPDX-License-Identifier: MIT */ -#include // std::signal #include // std::exit #include #include #include -#include "ruc/argparser.h" -#include "ruc/format/color.h" +#include "ruc/format/print.h" -#include "ast.h" #include "env/environment.h" #include "error.h" #include "eval.h" @@ -22,50 +19,51 @@ #include "printer.h" #include "reader.h" #include "readline.h" +#include "repl.h" #include "settings.h" namespace blaze { -static blaze::Readline s_readline; -static EnvironmentPtr s_outer_env = Environment::create(); +Readline g_readline; +EnvironmentPtr g_outer_env = Environment::create(); -static auto cleanup(int signal) -> void +auto Repl::cleanup(int signal) -> void { - print("\033[0m\n"); + ::print("\033[0m\n"); std::exit(signal); } -auto readline(const std::string& prompt) -> ValuePtr +auto Repl::readline(const std::string& prompt) -> ValuePtr { std::string input; - if (s_readline.get(input, s_readline.createPrompt(prompt))) { + if (g_readline.get(input, g_readline.createPrompt(prompt))) { return makePtr(input); } return makePtr(); } -auto read(std::string_view input) -> ValuePtr +auto Repl::read(std::string_view input) -> ValuePtr { Lexer lexer(input); lexer.tokenize(); - if (Settings::the().get("dump-lexer") == "1") { + if (Settings::the().getEnvBool("*DUMP-LEXER*")) { lexer.dump(); } Reader reader(std::move(lexer.tokens())); reader.read(); - if (Settings::the().get("dump-reader") == "1") { + if (Settings::the().getEnvBool("*DUMP-READER*")) { reader.dump(); } return reader.node(); } -auto eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr +auto Repl::eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr { if (env == nullptr) { - env = s_outer_env; + env = g_outer_env; } Eval eval(ast, env); @@ -74,14 +72,14 @@ auto eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr return eval.ast(); } -static auto print(ValuePtr value) -> std::string +auto Repl::print(ValuePtr value) -> std::string { Printer printer; return printer.print(value, true); } -static auto rep(std::string_view input, EnvironmentPtr env) -> std::string +auto Repl::rep(std::string_view input, EnvironmentPtr env) -> std::string { Error::the().clearErrors(); Error::the().setInput(input); @@ -89,7 +87,7 @@ static auto rep(std::string_view input, EnvironmentPtr env) -> std::string return print(eval(read(input), env)); } -static auto makeArgv(EnvironmentPtr env, std::vector arguments) -> void +auto Repl::makeArgv(EnvironmentPtr env, std::vector arguments) -> void { size_t count = arguments.size(); auto nodes = ValueVector(); @@ -100,58 +98,3 @@ static auto makeArgv(EnvironmentPtr env, std::vector arguments) -> } } // namespace blaze - -auto main(int argc, char* argv[]) -> int -{ - bool dump_lexer = false; - bool dump_reader = false; - bool pretty_print = false; - std::string_view history_path = "~/.blaze-history"; - std::vector arguments; - - // CLI arguments - ruc::ArgParser arg_parser; - arg_parser.addOption(dump_lexer, 'l', "dump-lexer", nullptr, nullptr); - arg_parser.addOption(dump_reader, 'r', "dump-reader", nullptr, nullptr); - arg_parser.addOption(pretty_print, 'c', "color", nullptr, nullptr); - arg_parser.addOption(history_path, 'h', "history-path", nullptr, nullptr, nullptr, ruc::ArgParser::Required::Yes); - // TODO: Add overload for addArgument(std::vector) - arg_parser.addArgument(arguments, "arguments", nullptr, nullptr, ruc::ArgParser::Required::No); - arg_parser.parse(argc, argv); - - // Set settings - blaze::Settings::the().set("dump-lexer", dump_lexer ? "1" : "0"); - blaze::Settings::the().set("dump-reader", dump_reader ? "1" : "0"); - blaze::Settings::the().set("pretty-print", pretty_print ? "1" : "0"); - - // Signal callbacks - std::signal(SIGINT, blaze::cleanup); - std::signal(SIGTERM, blaze::cleanup); - - blaze::Environment::loadFunctions(); - blaze::Environment::installFunctions(blaze::s_outer_env); - makeArgv(blaze::s_outer_env, arguments); - - if (arguments.size() > 0) { - rep(format("(load-file \"{}\")", arguments.front()), blaze::s_outer_env); - return 0; - } - - rep("(println (str \"Blaze [\" *host-language* \"]\"))", blaze::s_outer_env); - - blaze::s_readline = blaze::Readline(pretty_print, history_path); - - std::string input; - while (blaze::s_readline.get(input)) { - std::string output = rep(input, blaze::s_outer_env); - if (output.length() > 0) { - print("{}\n", output); - } - } - - if (pretty_print) { - print("\033[0m"); - } - - return 0; -} diff --git a/src/repl.h b/src/repl.h new file mode 100644 index 0000000..6fba5e2 --- /dev/null +++ b/src/repl.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2023 Riyyi + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include +#include + +#include "forward.h" +#include "readline.h" + +namespace blaze { + +class Repl { +public: + static auto cleanup(int signal) -> void; + static auto eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr; + static auto makeArgv(EnvironmentPtr env, std::vector arguments) -> void; + static auto print(ValuePtr value) -> std::string; + static auto read(std::string_view input) -> ValuePtr; + static auto readline(const std::string& prompt) -> ValuePtr; + static auto rep(std::string_view input, EnvironmentPtr env) -> std::string; +}; + +} // namespace blaze diff --git a/src/settings.cpp b/src/settings.cpp index 807173c..9f346fe 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -4,7 +4,14 @@ * SPDX-License-Identifier: MIT */ +#include // std::static_pointer_cast + +#include "ruc/meta/assert.h" + +#include "env/environment.h" +#include "forward.h" #include "settings.h" +#include "types.h" namespace blaze { @@ -14,4 +21,10 @@ std::string_view Settings::get(std::string_view key) const return m_settings.at(key); }; +bool Settings::getEnvBool(std::string_view key) const +{ + auto env = g_outer_env->get(key); + return is(env.get()) && std::static_pointer_cast(env)->state() == Constant::State::True; +} + } // namespace blaze diff --git a/src/settings.h b/src/settings.h index 20d086e..7aa63e3 100644 --- a/src/settings.h +++ b/src/settings.h @@ -6,12 +6,10 @@ #pragma once -#include "ruc/meta/assert.h" -#include "ruc/singleton.h" -#include #include #include -#include + +#include "ruc/singleton.h" namespace blaze { @@ -23,6 +21,8 @@ public: std::string_view get(std::string_view key) const; void set(std::string_view key, std::string_view value) { m_settings[key] = value; }; + bool getEnvBool(std::string_view key) const; + private: std::unordered_map m_settings; };