Browse Source

Everywhere: Split REPL from main(), put settings in environment

master
Riyyi 6 months ago
parent
commit
705e80ad6b
  1. 9
      src/ast.cpp
  2. 15
      src/env/environment.cpp
  3. 6
      src/env/environment.h
  4. 5
      src/env/functions/collection-modify.cpp
  5. 3
      src/env/functions/mutable.cpp
  6. 7
      src/env/functions/repl.cpp
  7. 2
      src/eval-special-form.cpp
  8. 3
      src/eval.h
  9. 10
      src/forward.h
  10. 84
      src/main.cpp
  11. 2
      src/printer.cpp
  12. 8
      src/reader.cpp
  13. 89
      src/repl.cpp
  14. 29
      src/repl.h
  15. 13
      src/settings.cpp
  16. 8
      src/settings.h

9
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) 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_bindings(bindings)
, m_documentation(documentation) , m_documentation(documentation)
, m_function(function) , m_function(function)
@ -243,14 +244,16 @@ Function::Function(const Function& that, ValuePtr meta)
// ----------------------------------------- // -----------------------------------------
Lambda::Lambda(const std::vector<std::string>& bindings, ValuePtr body, EnvironmentPtr env) Lambda::Lambda(const std::vector<std::string>& bindings, ValuePtr body, EnvironmentPtr env)
: m_bindings(bindings) : Callable()
, m_bindings(bindings)
, m_body(body) , m_body(body)
, m_env(env) , m_env(env)
{ {
} }
Lambda::Lambda(const Lambda& that) Lambda::Lambda(const Lambda& that)
: m_bindings(that.m_bindings) : Callable()
, m_bindings(that.m_bindings)
, m_body(that.m_body) , m_body(that.m_body)
, m_env(that.m_env) , m_env(that.m_env)
{ {

15
src/env/environment.cpp vendored

@ -15,6 +15,7 @@
#include "env/environment.h" #include "env/environment.h"
#include "error.h" #include "error.h"
#include "forward.h" #include "forward.h"
#include "repl.h"
namespace blaze { namespace blaze {
@ -135,21 +136,21 @@ void Environment::installFunctions(EnvironmentPtr env)
} }
for (const auto& lambda : s_lambdas) { for (const auto& lambda : s_lambdas) {
// Ensure all s-exprs are run with (do) // 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)) { if (exists(symbol)) {
m_values.erase(symbol); m_values.erase(std::string(symbol));
} }
m_values.emplace(symbol, value); m_values.emplace(symbol, value);
@ -157,10 +158,10 @@ ValuePtr Environment::set(const std::string& symbol, ValuePtr value)
return value; return value;
} }
ValuePtr Environment::get(const std::string& symbol) ValuePtr Environment::get(std::string_view symbol)
{ {
if (exists(symbol)) { if (exists(symbol)) {
return m_values[symbol]; return m_values[std::string(symbol)];
} }
if (m_outer) { if (m_outer) {

6
src/env/environment.h vendored

@ -37,9 +37,9 @@ public:
static void registerFunction(FunctionParts function_parts); static void registerFunction(FunctionParts function_parts);
static void installFunctions(EnvironmentPtr env); static void installFunctions(EnvironmentPtr env);
bool exists(const std::string& symbol); bool exists(std::string_view symbol);
ValuePtr set(const std::string& symbol, ValuePtr value); ValuePtr set(std::string_view symbol, ValuePtr value);
ValuePtr get(const std::string& symbol); ValuePtr get(std::string_view symbol);
private: private:
Environment() {} Environment() {}

5
src/env/functions/collection-modify.cpp vendored

@ -12,6 +12,7 @@
#include "env/environment.h" #include "env/environment.h"
#include "env/macro.h" #include "env/macro.h"
#include "forward.h" #include "forward.h"
#include "repl.h"
#include "util.h" #include "util.h"
namespace blaze { namespace blaze {
@ -47,7 +48,7 @@ void Environment::loadCollectionModify()
} }
else { else {
auto lambda = std::static_pointer_cast<Lambda>(callable); auto lambda = std::static_pointer_cast<Lambda>(callable);
value = eval(lambda->body(), Environment::create(lambda, std::move(arguments))); value = Repl::eval(lambda->body(), Environment::create(lambda, std::move(arguments)));
} }
return value; return value;
@ -152,7 +153,7 @@ void Environment::loadCollectionModify()
auto lambda = std::static_pointer_cast<Lambda>(callable); auto lambda = std::static_pointer_cast<Lambda>(callable);
auto collection_nodes = collection->nodesRead(); auto collection_nodes = collection->nodesRead();
for (size_t i = 0; i < count; ++i) { 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] })));
} }
} }

3
src/env/functions/mutable.cpp vendored

@ -11,6 +11,7 @@
#include "env/environment.h" #include "env/environment.h"
#include "env/macro.h" #include "env/macro.h"
#include "forward.h" #include "forward.h"
#include "repl.h"
#include "util.h" #include "util.h"
namespace blaze { namespace blaze {
@ -82,7 +83,7 @@ void Environment::loadMutable()
} }
else { else {
auto lambda = std::static_pointer_cast<Lambda>(callable); auto lambda = std::static_pointer_cast<Lambda>(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); return atom->reset(value);

7
src/env/functions/repl.cpp vendored

@ -10,6 +10,7 @@
#include "ast.h" #include "ast.h"
#include "env/macro.h" #include "env/macro.h"
#include "repl.h"
#include "util.h" #include "util.h"
namespace blaze { namespace blaze {
@ -27,7 +28,7 @@ void Environment::loadRepl()
VALUE_CAST(node, String, (*begin)); VALUE_CAST(node, String, (*begin));
std::string input = node->data(); std::string input = node->data();
return read(input); return Repl::read(input);
}); });
// Read file contents // Read file contents
@ -56,7 +57,7 @@ void Environment::loadRepl()
VALUE_CAST(prompt, String, (*begin)); VALUE_CAST(prompt, String, (*begin));
return readline(prompt->data()); return Repl::readline(prompt->data());
}); });
// REPL eval // REPL eval
@ -67,7 +68,7 @@ void Environment::loadRepl()
{ {
CHECK_ARG_COUNT_IS("eval", SIZE(), 1); CHECK_ARG_COUNT_IS("eval", SIZE(), 1);
return eval(*begin, nullptr); return Repl::eval(*begin, nullptr);
}); });
} }

2
src/eval-special-form.cpp

@ -96,7 +96,7 @@ ValuePtr Eval::evalDescribe(const ValueVector& nodes, EnvironmentPtr env)
std::string documentation; std::string documentation;
std::string value_string; 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 bold = fg(ruc::format::TerminalColor::None) | ruc::format::Emphasis::Bold;
auto describe = [&]() { auto describe = [&]() {

3
src/eval.h

@ -8,8 +8,7 @@
#include <vector> #include <vector>
#include "env/environment.h" #include "forward.h" // EnvironmentPtr
#include "forward.h"
namespace blaze { namespace blaze {

10
src/forward.h

@ -25,11 +25,15 @@ typedef ValueVector::const_reverse_iterator ValueVectorConstReverseIt;
class Environment; class Environment;
typedef std::shared_ptr<Environment> EnvironmentPtr; typedef std::shared_ptr<Environment> EnvironmentPtr;
class Readline;
// ----------------------------------------- // -----------------------------------------
// Functions // Functions
extern ValuePtr readline(const std::string& prompt); // -----------------------------------------
extern ValuePtr read(std::string_view input); // Variables
extern ValuePtr eval(ValuePtr ast, EnvironmentPtr env);
extern Readline g_readline;
extern EnvironmentPtr g_outer_env;
} // namespace blaze } // namespace blaze

84
src/main.cpp

@ -0,0 +1,84 @@
/*
* Copyright (C) 2023 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#include <csignal> // std::signal
#include <string>
#include <string_view>
#include <vector>
#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<std::string> 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<std::string_view>)
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<Constant>(dump_lexer));
g_outer_env->set("*DUMP-READER*", makePtr<Constant>(dump_reader));
g_outer_env->set("*PRETTY-PRINT*", makePtr<Constant>(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);
}

2
src/printer.cpp

@ -66,7 +66,7 @@ void Printer::init()
void Printer::printImpl(ValuePtr value, bool print_readably) 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 { auto printSpacing = [this]() -> void {
if (!m_first_node && !m_previous_node_is_list) { if (!m_first_node && !m_previous_node_is_list) {

8
src/reader.cpp

@ -147,7 +147,7 @@ ValuePtr Reader::readList()
nodes.push_back(node); 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"); Error::the().add("expected ')', got EOF");
return nullptr; return nullptr;
} }
@ -168,7 +168,7 @@ ValuePtr Reader::readVector()
nodes.push_back(node); 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"); Error::the().add("expected ']', got EOF");
} }
@ -201,7 +201,7 @@ ValuePtr Reader::readHashMap()
elements.insert_or_assign(HashMap::getKeyString(key), value); 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"); Error::the().add("expected '}', got EOF");
return nullptr; return nullptr;
} }
@ -378,7 +378,7 @@ void Reader::dumpImpl(ValuePtr node)
std::string indentation = std::string(m_indentation * INDENTATION_WIDTH, ' '); std::string indentation = std::string(m_indentation * INDENTATION_WIDTH, ' ');
print("{}", indentation); 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 blue = fg(ruc::format::TerminalColor::BrightBlue);
auto yellow = fg(ruc::format::TerminalColor::Yellow); auto yellow = fg(ruc::format::TerminalColor::Yellow);

89
src/repl.cpp

@ -4,16 +4,13 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#include <csignal> // std::signal
#include <cstdlib> // std::exit #include <cstdlib> // std::exit
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include "ruc/argparser.h" #include "ruc/format/print.h"
#include "ruc/format/color.h"
#include "ast.h"
#include "env/environment.h" #include "env/environment.h"
#include "error.h" #include "error.h"
#include "eval.h" #include "eval.h"
@ -22,50 +19,51 @@
#include "printer.h" #include "printer.h"
#include "reader.h" #include "reader.h"
#include "readline.h" #include "readline.h"
#include "repl.h"
#include "settings.h" #include "settings.h"
namespace blaze { namespace blaze {
static blaze::Readline s_readline; Readline g_readline;
static EnvironmentPtr s_outer_env = Environment::create(); 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); std::exit(signal);
} }
auto readline(const std::string& prompt) -> ValuePtr auto Repl::readline(const std::string& prompt) -> ValuePtr
{ {
std::string input; std::string input;
if (s_readline.get(input, s_readline.createPrompt(prompt))) { if (g_readline.get(input, g_readline.createPrompt(prompt))) {
return makePtr<String>(input); return makePtr<String>(input);
} }
return makePtr<Constant>(); return makePtr<Constant>();
} }
auto read(std::string_view input) -> ValuePtr auto Repl::read(std::string_view input) -> ValuePtr
{ {
Lexer lexer(input); Lexer lexer(input);
lexer.tokenize(); lexer.tokenize();
if (Settings::the().get("dump-lexer") == "1") { if (Settings::the().getEnvBool("*DUMP-LEXER*")) {
lexer.dump(); lexer.dump();
} }
Reader reader(std::move(lexer.tokens())); Reader reader(std::move(lexer.tokens()));
reader.read(); reader.read();
if (Settings::the().get("dump-reader") == "1") { if (Settings::the().getEnvBool("*DUMP-READER*")) {
reader.dump(); reader.dump();
} }
return reader.node(); return reader.node();
} }
auto eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr auto Repl::eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr
{ {
if (env == nullptr) { if (env == nullptr) {
env = s_outer_env; env = g_outer_env;
} }
Eval eval(ast, env); Eval eval(ast, env);
@ -74,14 +72,14 @@ auto eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr
return eval.ast(); return eval.ast();
} }
static auto print(ValuePtr value) -> std::string auto Repl::print(ValuePtr value) -> std::string
{ {
Printer printer; Printer printer;
return printer.print(value, true); 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().clearErrors();
Error::the().setInput(input); 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)); return print(eval(read(input), env));
} }
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void auto Repl::makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
{ {
size_t count = arguments.size(); size_t count = arguments.size();
auto nodes = ValueVector(); auto nodes = ValueVector();
@ -100,58 +98,3 @@ static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) ->
} }
} // namespace blaze } // 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<std::string> 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<std::string_view>)
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;
}

29
src/repl.h

@ -0,0 +1,29 @@
/*
* Copyright (C) 2023 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <string>
#include <string_view>
#include <vector>
#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<std::string> 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

13
src/settings.cpp

@ -4,7 +4,14 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#include <memory> // std::static_pointer_cast
#include "ruc/meta/assert.h"
#include "env/environment.h"
#include "forward.h"
#include "settings.h" #include "settings.h"
#include "types.h"
namespace blaze { namespace blaze {
@ -14,4 +21,10 @@ std::string_view Settings::get(std::string_view key) const
return m_settings.at(key); return m_settings.at(key);
}; };
bool Settings::getEnvBool(std::string_view key) const
{
auto env = g_outer_env->get(key);
return is<Constant>(env.get()) && std::static_pointer_cast<Constant>(env)->state() == Constant::State::True;
}
} // namespace blaze } // namespace blaze

8
src/settings.h

@ -6,12 +6,10 @@
#pragma once #pragma once
#include "ruc/meta/assert.h"
#include "ruc/singleton.h"
#include <string>
#include <string_view> #include <string_view>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "ruc/singleton.h"
namespace blaze { namespace blaze {
@ -23,6 +21,8 @@ public:
std::string_view get(std::string_view key) const; std::string_view get(std::string_view key) const;
void set(std::string_view key, std::string_view value) { m_settings[key] = value; }; void set(std::string_view key, std::string_view value) { m_settings[key] = value; };
bool getEnvBool(std::string_view key) const;
private: private:
std::unordered_map<std::string_view, std::string_view> m_settings; std::unordered_map<std::string_view, std::string_view> m_settings;
}; };

Loading…
Cancel
Save