Browse Source

Main+Readline+Env: Add readline core function

master
Riyyi 1 year ago
parent
commit
6e0fe3a2f5
  1. 3
      src/forward.h
  2. 10
      src/functions.cpp
  3. 33
      src/readline.cpp
  4. 6
      src/readline.h
  5. 1
      src/step9_try.cpp
  6. 181
      src/stepA_mal.cpp

3
src/forward.h

@ -22,8 +22,9 @@ typedef std::shared_ptr<Environment> EnvironmentPtr;
// -----------------------------------------
// Functions
extern ValuePtr readline(const std::string& prompt);
extern ValuePtr read(std::string_view input);
ValuePtr eval(ValuePtr ast, EnvironmentPtr env);
extern ValuePtr eval(ValuePtr ast, EnvironmentPtr env);
extern void installFunctions(EnvironmentPtr env);

10
src/functions.cpp

@ -786,6 +786,16 @@ ADD_FUNCTION(
return result;
});
ADD_FUNCTION(
"readline",
{
CHECK_ARG_COUNT_IS("readline", nodes.size(), 1);
VALUE_CAST(prompt, String, nodes.front());
return readline(prompt->data());
});
// -----------------------------------------
void installFunctions(EnvironmentPtr env)

33
src/readline.cpp

@ -13,6 +13,7 @@
#include <string_view>
#include "ruc/format/color.h"
#include "ruc/format/print.h"
#include "readline.h"
@ -22,13 +23,7 @@ Readline::Readline(bool pretty_print, std::string_view history_path)
: m_pretty_print(pretty_print)
, m_history_path(tilde_expand(history_path.data()))
{
if (!pretty_print) {
m_prompt = "user> ";
}
else {
m_prompt = format(fg(ruc::format::TerminalColor::Blue), "user>");
m_prompt += format(" \033[1m");
}
m_prompt = createPrompt("user> ");
read_history(m_history_path);
}
@ -40,9 +35,24 @@ Readline::~Readline()
// -----------------------------------------
bool Readline::get(std::string& output)
std::string Readline::createPrompt(const std::string& prompt)
{
if (!m_pretty_print) {
return prompt;
}
return format(fg(ruc::format::TerminalColor::Blue), "{}", prompt)
+ format("\033[1m");
}
bool Readline::get(std::string& output, const std::string& prompt)
{
char* line = readline(m_prompt.c_str());
char* line = readline(prompt.c_str());
if (m_pretty_print) {
print("\033[0m");
}
if (line == nullptr) {
return false;
}
@ -57,4 +67,9 @@ bool Readline::get(std::string& output)
return true;
}
bool Readline::get(std::string& output)
{
return get(output, m_prompt);
}
} // namespace blaze

6
src/readline.h

@ -15,15 +15,19 @@ namespace blaze {
class Readline {
public:
Readline() = default;
Readline(bool pretty_print, std::string_view history_path);
virtual ~Readline();
std::string createPrompt(const std::string& prompt);
bool get(std::string& output, const std::string& prompt);
bool get(std::string& output);
private:
bool m_pretty_print { false };
std::string m_prompt;
char* m_history_path;
std::string m_prompt;
};
} // namespace blaze

1
src/step9_try.cpp

@ -126,7 +126,6 @@ auto main(int argc, char* argv[]) -> int
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);

181
src/stepA_mal.cpp

@ -0,0 +1,181 @@
/*
* Copyright (C) 2023 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#include <csignal> // std::signal
#include <cstdlib> // std::exit
#include <string>
#include <string_view>
#include <vector>
#include "ruc/argparser.h"
#include "ruc/format/color.h"
#include "ast.h"
#include "environment.h"
#include "error.h"
#include "eval.h"
#include "forward.h"
#include "lexer.h"
#include "printer.h"
#include "reader.h"
#include "readline.h"
#include "settings.h"
#if 1
namespace blaze {
static blaze::Readline s_readline;
static EnvironmentPtr s_outer_env = Environment::create();
static auto cleanup(int signal) -> void
{
print("\033[0m\n");
std::exit(signal);
}
auto readline(const std::string& prompt) -> ValuePtr
{
std::string input;
if (s_readline.get(input, s_readline.createPrompt(prompt))) {
return makePtr<String>(input);
}
return makePtr<Constant>();
}
auto read(std::string_view input) -> ValuePtr
{
Lexer lexer(input);
lexer.tokenize();
if (Settings::the().get("dump-lexer") == "1") {
lexer.dump();
}
Reader reader(std::move(lexer.tokens()));
reader.read();
if (Settings::the().get("dump-reader") == "1") {
reader.dump();
}
return reader.node();
}
auto eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr
{
if (env == nullptr) {
env = s_outer_env;
}
Eval eval(ast, env);
eval.eval();
return eval.ast();
}
static auto print(ValuePtr exp) -> std::string
{
Printer printer;
return printer.print(exp, true);
}
static auto rep(std::string_view input, EnvironmentPtr env) -> std::string
{
Error::the().clearErrors();
Error::the().setInput(input);
return print(eval(read(input), env));
}
static std::string_view lambdaTable[] = {
"(def! not (fn* (cond) (if cond false true)))",
"(def! load-file (fn* (filename) \
(eval (read-string (str \"(do \" (slurp filename) \"\nnil)\")))))",
"(defmacro! cond (fn* (& xs) \
(if (> (count xs) 0) \
(list 'if (first xs) \
(if (> (count xs) 1) \
(nth xs 1) \
(throw \"odd number of forms to cond\")) \
(cons 'cond (rest (rest xs)))))))",
"(def! *host-language* \"C++\")",
};
static auto installLambdas(EnvironmentPtr env) -> void
{
for (auto function : lambdaTable) {
rep(function, env);
}
}
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
{
auto list = makePtr<List>();
if (arguments.size() > 1) {
for (auto it = arguments.begin() + 1; it != arguments.end(); ++it) {
list->add(makePtr<String>(*it));
}
}
env->set("*ARGV*", list);
}
} // 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);
installFunctions(blaze::s_outer_env);
installLambdas(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 \"Mal [\" *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;
}
#endif
Loading…
Cancel
Save