MalachScript/repl/main.cpp

136 lines
5.1 KiB
C++

#include <fstream>
#include <ncurses.h>
#include <sstream>
#include "../src/Binder/Binder.hpp"
#include "../src/Diagnostics/DiagnosticTypeEN_US.hpp"
#include "../src/Parser/Lexer/Lexer.hpp"
#include "../src/Parser/Parser.hpp"
#include "InputWindow.hpp"
#include "ResultWindow.hpp"
namespace MalachScriptRepl {
void ParseAndUpdate(const std::vector<std::string>& lines, WINDOW* diagnosticsWindow, ResultWindow* parsedWindow,
MalachScriptRepl::InputWindow& inputWindow) {
std::string script;
for (size_t i = 0; i < lines.size(); i++) {
script += lines[i];
if (i != lines.size() - 1) {
script += '\n';
}
}
std::ofstream outfile;
outfile.open("script.ms", std::ios::out | std::ios::trunc);
outfile << (char*)script.data();
outfile.close();
auto logger = MalachScript::Diagnostics::Logger();
auto lexer = MalachScript::Parser::Lexer("diag", script, &logger);
const auto* firstToken = lexer.Lex();
const auto* parsedResult = MalachScript::Parser::Parser::Parse(firstToken, &logger);
auto* ns = new MalachScript::Binder::BoundNamespace();
const MalachScript::Binder::Binder::log_func log =
[&logger](MalachScript::Diagnostics::DiagnosticLevel level, MalachScript::Diagnostics::DiagnosticType type,
const MalachScript::ScriptTextSpan& span,
const std::vector<std::string>& formats) { logger.Log(level, type, span, formats); };
MalachScript::Binder::Binder::Bind(ns, {parsedResult}, log);
const MalachScript::Diagnostics::Diagnostic* diag = nullptr;
wclear(diagnosticsWindow);
if (!logger.GetMessages().empty()) {
diag = &logger.GetMessages()[0];
wattron(diagnosticsWindow, COLOR_PAIR(1));
waddch(diagnosticsWindow, '[');
waddstr(diagnosticsWindow, "Error");
waddch(diagnosticsWindow, ']');
wattroff(diagnosticsWindow, COLOR_PAIR(1));
waddch(diagnosticsWindow, ' ');
waddstr(diagnosticsWindow, std::to_string(diag->GetSpan().GetStart() + 1).c_str());
waddch(diagnosticsWindow, '-');
waddstr(diagnosticsWindow, std::to_string(diag->GetSpan().GetEnd() + 1).c_str());
waddch(diagnosticsWindow, ' ');
waddstr(diagnosticsWindow, MalachScript::Diagnostics::DiagnosticTypeHelper::ToEnglishString(diag).c_str());
waddch(diagnosticsWindow, '\n');
}
wrefresh(diagnosticsWindow);
parsedWindow->SetResult(parsedResult, ns);
inputWindow.SetScriptWithDiagnostics(script, diag);
delete parsedResult;
}
int Run() {
setlocale(LC_ALL, "");
initscr();
cbreak();
noecho();
keypad(stdscr, true);
set_tabsize(4);
start_color();
init_pair(1, COLOR_RED, COLOR_BLACK);
clear();
int maxX;
int maxY;
getmaxyx(stdscr, maxY, maxX);
wresize(stdscr, maxY, maxX);
wrefresh(stdscr);
const int inputFieldSize = 30;
wborder(stdscr, 0, 0, 0, 0, 0, 0, 0, 0);
wmove(stdscr, 31, 1);
whline(stdscr, ACS_HLINE, maxX - 2);
wmove(stdscr, 32, maxX / 2);
wvline(stdscr, ACS_VLINE, 25);
wrefresh(stdscr);
[[maybe_unused]] auto* diagnosticsWindow = newwin(25, (maxX - 4) / 2, 32, 2);
auto* parsedResultWindow = new ResultWindow(25, (maxX - 4) / 2 - 2, 32, (maxX - 4) / 2 + 4);
auto inputWindow = MalachScriptRepl::InputWindow(inputFieldSize, maxX - 3, 1, 2);
inputWindow.RegisterOnChange(
[diagnosticsWindow, parsedResultWindow, &inputWindow](const std::vector<std::string>& lines) {
ParseAndUpdate(lines, diagnosticsWindow, parsedResultWindow, inputWindow);
});
int c;
bool running = true;
while (running) {
c = inputWindow.GetInput();
switch (c) {
case 27: running = false; break;
case KEY_LEFT: inputWindow.MoveCursorLeft(); break;
case KEY_RIGHT: inputWindow.MoveCursorRight(); break;
case KEY_UP: inputWindow.MoveCursorUp(); break;
case KEY_DOWN: inputWindow.MoveCursorDown(); break;
case KEY_BACKSPACE:
case 127: inputWindow.Backspace(); break;
case 10:
case KEY_ENTER: inputWindow.Return(); break;
case 9:
case KEY_STAB: inputWindow.Tab(); break;
case KEY_END: inputWindow.GoToEndOfLine(); break;
case KEY_HOME: inputWindow.GoToStartOfLine(); break;
case KEY_F(1): parsedResultWindow->SetView(ResultWindow::View::ParseTree); break;
case KEY_F(2): parsedResultWindow->SetView(ResultWindow::View::TypeList); break;
default: inputWindow.Input(c); break;
}
inputWindow.Refresh();
}
endwin();
return EXIT_SUCCESS;
}
}
int main([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[]) { return MalachScriptRepl::Run(); }