More work on binder type registration, support in REPL to show registered types.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
093ffde6bc
commit
8660933f27
|
@ -86,7 +86,7 @@ virtprop ::= ['private' | 'protected'] type ['&'] identifier '{' {('g
|
||||||
func ::= {'shared' | 'external'} ['private' | 'protected'] [((type ['&']) | '~')] identifier paramlist ['const'] funcattr (';' | statblock);
|
func ::= {'shared' | 'external'} ['private' | 'protected'] [((type ['&']) | '~')] identifier paramlist ['const'] funcattr (';' | statblock);
|
||||||
funcdef ::= {'external' | 'shared'} 'funcdef' type ['&'] identifier paramlist ';'
|
funcdef ::= {'external' | 'shared'} 'funcdef' type ['&'] identifier paramlist ';'
|
||||||
class ::= {'shared' | 'abstract' | 'final' | 'external'} 'class' identifier
|
class ::= {'shared' | 'abstract' | 'final' | 'external'} 'class' identifier
|
||||||
(';' | ([':' identifier {',' identifier}] '{' {virtprop | func | var | funcdef} '}'));
|
(';' | ([':' identifier {',' identifier}] '{' {virtprop | func | var | funcdef | class} '}'));
|
||||||
mixin ::= 'mixin' class;
|
mixin ::= 'mixin' class;
|
||||||
enum ::= {'shared' | 'external'} 'enum' identifier [ ':' primtype ] (';' | ('{' identifier ['=' expr] {',' identifier ['=' expr]} '}'));
|
enum ::= {'shared' | 'external'} 'enum' identifier [ ':' primtype ] (';' | ('{' identifier ['=' expr] {',' identifier ['=' expr]} '}'));
|
||||||
import ::= 'import' type ['&'] identifier paramlist funcattr 'from' string ';';
|
import ::= 'import' type ['&'] identifier paramlist funcattr 'from' string ';';
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef MALACHSCRIPT_RESULTWINDOW_HPP
|
||||||
|
#define MALACHSCRIPT_RESULTWINDOW_HPP
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include "../src/Binder/BoundNamespaceStringifier.hpp"
|
||||||
|
#include "../src/Parser/Statements/ParsedStatementStringifier.hpp"
|
||||||
|
|
||||||
|
namespace MalachScriptRepl {
|
||||||
|
class ResultWindow {
|
||||||
|
public:
|
||||||
|
enum class View { ParseTree, TypeList };
|
||||||
|
|
||||||
|
ResultWindow(int height, int width, int y, int x) { _window = newwin(height, width, y, x); }
|
||||||
|
|
||||||
|
void SetResult(const MalachScript::Parser::ParsedStatement* statement,
|
||||||
|
const MalachScript::Binder::BoundNamespace* ns) {
|
||||||
|
std::stringstream parsedTreeStringStream;
|
||||||
|
MalachScript::Parser::ParsedStatementStringifier::Stringify(statement, parsedTreeStringStream, "", true);
|
||||||
|
_parseTree = parsedTreeStringStream.str();
|
||||||
|
|
||||||
|
std::stringstream boundNamespaceStringStream;
|
||||||
|
MalachScript::Binder::BoundNamespaceStringifier::Stringify(ns, boundNamespaceStringStream);
|
||||||
|
_boundNamespace = boundNamespaceStringStream.str();
|
||||||
|
|
||||||
|
switch (_view) {
|
||||||
|
case View::ParseTree: SetParseTree(); break;
|
||||||
|
case View::TypeList: SetTypeList(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetView(View view) {
|
||||||
|
_view = view;
|
||||||
|
switch (view) {
|
||||||
|
case View::ParseTree: SetParseTree(); break;
|
||||||
|
case View::TypeList: SetTypeList(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
WINDOW* _window;
|
||||||
|
std::string _parseTree;
|
||||||
|
std::string _boundNamespace;
|
||||||
|
View _view;
|
||||||
|
|
||||||
|
inline void SetParseTree() {
|
||||||
|
wclear(_window);
|
||||||
|
waddstr(_window, _parseTree.c_str());
|
||||||
|
wrefresh(_window);
|
||||||
|
}
|
||||||
|
inline void SetTypeList() {
|
||||||
|
wclear(_window);
|
||||||
|
waddstr(_window, _boundNamespace.c_str());
|
||||||
|
wrefresh(_window);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MALACHSCRIPT_RESULTWINDOW_HPP
|
225
repl/main.cpp
225
repl/main.cpp
|
@ -1,129 +1,136 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "../src/Binder/Binder.hpp"
|
||||||
#include "../src/Diagnostics/DiagnosticTypeEN_US.hpp"
|
#include "../src/Diagnostics/DiagnosticTypeEN_US.hpp"
|
||||||
#include "../src/Parser/Lexer/Lexer.hpp"
|
#include "../src/Parser/Lexer/Lexer.hpp"
|
||||||
#include "../src/Parser/Parser.hpp"
|
#include "../src/Parser/Parser.hpp"
|
||||||
#include "../src/Parser/Statements/ParsedStatementStringifier.hpp"
|
|
||||||
#include "InputWindow.hpp"
|
#include "InputWindow.hpp"
|
||||||
|
#include "ResultWindow.hpp"
|
||||||
|
|
||||||
void ParseAndUpdate(const std::vector<std::string>& lines, WINDOW* diagnosticsWindow, WINDOW* parsedWindow,
|
namespace MalachScriptRepl {
|
||||||
MalachScriptRepl::InputWindow& inputWindow) {
|
void ParseAndUpdate(const std::vector<std::string>& lines, WINDOW* diagnosticsWindow, ResultWindow* parsedWindow,
|
||||||
std::string script;
|
MalachScriptRepl::InputWindow& inputWindow) {
|
||||||
for (size_t i = 0; i < lines.size(); i++) {
|
std::string script;
|
||||||
script += lines[i];
|
for (size_t i = 0; i < lines.size(); i++) {
|
||||||
if (i != lines.size() - 1) {
|
script += lines[i];
|
||||||
script += '\n';
|
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, "diag", &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::TextSpan& 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream outfile;
|
int Run() {
|
||||||
outfile.open("script.ms", std::ios::out | std::ios::trunc);
|
setlocale(LC_ALL, "");
|
||||||
outfile << (char*)script.data();
|
initscr();
|
||||||
outfile.close();
|
cbreak();
|
||||||
|
noecho();
|
||||||
|
keypad(stdscr, true);
|
||||||
|
set_tabsize(4);
|
||||||
|
|
||||||
auto logger = MalachScript::Diagnostics::Logger();
|
start_color();
|
||||||
auto lexer = MalachScript::Parser::Lexer("diag", script, &logger);
|
init_pair(1, COLOR_RED, COLOR_BLACK);
|
||||||
const auto* firstToken = lexer.Lex();
|
clear();
|
||||||
const auto* parsedResult = MalachScript::Parser::Parser::Parse(firstToken, "diag", &logger);
|
|
||||||
|
|
||||||
const MalachScript::Diagnostics::Diagnostic* diag = nullptr;
|
int maxX;
|
||||||
wclear(diagnosticsWindow);
|
int maxY;
|
||||||
|
getmaxyx(stdscr, maxY, maxX);
|
||||||
|
wresize(stdscr, maxY, maxX);
|
||||||
|
wrefresh(stdscr);
|
||||||
|
|
||||||
if (!logger.GetMessages().empty()) {
|
const int inputFieldSize = 30;
|
||||||
diag = &logger.GetMessages()[0];
|
|
||||||
|
|
||||||
wattron(diagnosticsWindow, COLOR_PAIR(1));
|
wborder(stdscr, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
waddch(diagnosticsWindow, '[');
|
wmove(stdscr, 31, 1);
|
||||||
waddstr(diagnosticsWindow, "Error");
|
whline(stdscr, ACS_HLINE, maxX - 2);
|
||||||
waddch(diagnosticsWindow, ']');
|
wmove(stdscr, 32, maxX / 2);
|
||||||
wattroff(diagnosticsWindow, COLOR_PAIR(1));
|
wvline(stdscr, ACS_VLINE, 25);
|
||||||
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());
|
wrefresh(stdscr);
|
||||||
|
|
||||||
waddch(diagnosticsWindow, '\n');
|
[[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;
|
||||||
}
|
}
|
||||||
wrefresh(diagnosticsWindow);
|
|
||||||
|
|
||||||
wclear(parsedWindow);
|
|
||||||
std::stringstream ss;
|
|
||||||
MalachScript::Parser::ParsedStatementStringifier::Stringify(parsedResult, ss, "", true);
|
|
||||||
|
|
||||||
waddstr(parsedWindow, ss.str().c_str());
|
|
||||||
wrefresh(parsedWindow);
|
|
||||||
|
|
||||||
inputWindow.SetScriptWithDiagnostics(script, diag);
|
|
||||||
delete parsedResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[]) {
|
int main([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[]) { return MalachScriptRepl::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 = newwin(25, (maxX - 4) / 2 - 2, 32, (maxX - 4) / 2 + 4);
|
|
||||||
wrefresh(parsedResultWindow);
|
|
||||||
|
|
||||||
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;
|
|
||||||
default: inputWindow.Input(c); break;
|
|
||||||
}
|
|
||||||
inputWindow.Refresh();
|
|
||||||
}
|
|
||||||
endwin();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
|
@ -54,13 +54,23 @@ namespace MalachScript::Binder {
|
||||||
case Parser::ParsedStatementKind::Class: {
|
case Parser::ParsedStatementKind::Class: {
|
||||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||||
auto identifier = s->GetIdentifier();
|
auto identifier = s->GetIdentifier();
|
||||||
if (activeType.has_value()) {
|
auto type = ns->ResolveType(s->GetIdentifier());
|
||||||
|
if (!type.has_value()) {
|
||||||
|
if (activeType.has_value()) {
|
||||||
|
type = activeType.value()->ResolveType(s->GetIdentifier());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto* type = new BoundType(s->GetClassAttr());
|
if (type.has_value()) {
|
||||||
|
log(DiagnosticLevel::Error, DiagnosticType::TypeAlreadyDefined, s->GetSpan(),
|
||||||
|
{identifier.GetStdString()});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = new BoundType(identifier, s->GetClassAttr());
|
||||||
if (activeType.has_value()) {
|
if (activeType.has_value()) {
|
||||||
activeType.value()->RegisterType(identifier, type);
|
activeType.value()->RegisterType(identifier, type.value());
|
||||||
} else {
|
} else {
|
||||||
ns->RegisterType(identifier, type);
|
ns->RegisterType(identifier, type.value());
|
||||||
}
|
}
|
||||||
for (const auto& child : s->GetBody()) {
|
for (const auto& child : s->GetBody()) {
|
||||||
TypeRegistrationFirstPass(ns, child.get(), type, log);
|
TypeRegistrationFirstPass(ns, child.get(), type, log);
|
||||||
|
@ -92,7 +102,12 @@ namespace MalachScript::Binder {
|
||||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||||
auto type = ns->ResolveType(s->GetIdentifier());
|
auto type = ns->ResolveType(s->GetIdentifier());
|
||||||
if (!type.has_value()) {
|
if (!type.has_value()) {
|
||||||
throw std::logic_error("Shouldn't be reached");
|
if (activeType.has_value()) {
|
||||||
|
type = activeType.value()->ResolveType(s->GetIdentifier());
|
||||||
|
}
|
||||||
|
if (!type.has_value()) {
|
||||||
|
throw std::logic_error("Shouldn't be reached");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const auto& inherits : s->GetInherits()) {
|
for (const auto& inherits : s->GetInherits()) {
|
||||||
auto inheritType = ResolveType(ns, inherits);
|
auto inheritType = ResolveType(ns, inherits);
|
||||||
|
@ -152,7 +167,12 @@ namespace MalachScript::Binder {
|
||||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||||
auto type = ns->ResolveType(s->GetIdentifier());
|
auto type = ns->ResolveType(s->GetIdentifier());
|
||||||
if (!type.has_value()) {
|
if (!type.has_value()) {
|
||||||
throw std::logic_error("Shouldn't be reached");
|
if (activeType.has_value()) {
|
||||||
|
type = activeType.value()->ResolveType(s->GetIdentifier());
|
||||||
|
}
|
||||||
|
if (!type.has_value()) {
|
||||||
|
throw std::logic_error("Shouldn't be reached");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const auto& child : s->GetBody()) {
|
for (const auto& child : s->GetBody()) {
|
||||||
TypeRegistrationThirdPass(ns, child.get(), type.value(), log);
|
TypeRegistrationThirdPass(ns, child.get(), type.value(), log);
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#ifndef MALACHSCRIPT_BOUNDNAMESPACESTRINGIFIER_HPP
|
||||||
|
#define MALACHSCRIPT_BOUNDNAMESPACESTRINGIFIER_HPP
|
||||||
|
|
||||||
|
#include "BoundNamespace.hpp"
|
||||||
|
|
||||||
|
template <typename K, typename V> static std::vector<std::pair<K, V>> mapToVector(const std::unordered_map<K, V>& map) {
|
||||||
|
auto vec = std::vector<std::pair<K, V>>(map.begin(), map.end());
|
||||||
|
std::reverse(vec.begin(), vec.end());
|
||||||
|
return vec;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace MalachScript::Binder {
|
||||||
|
class BoundNamespaceStringifier {
|
||||||
|
static void StringifyField(const MalachScript::Identifier& identifier, const BoundVariable* field,
|
||||||
|
std::stringstream& stream, const std::string& prefix, bool isLast) {
|
||||||
|
stream << prefix;
|
||||||
|
stream << (isLast ? "└──" : "├──");
|
||||||
|
stream << identifier << ": " << field->GetType()->GetIdentifier();
|
||||||
|
}
|
||||||
|
static void StringifyType(const MalachScript::Identifier& identifier, const BoundType* type,
|
||||||
|
std::stringstream& stream, const std::string& prefix, bool isLast) {
|
||||||
|
stream << prefix;
|
||||||
|
stream << (isLast ? "└──" : "├──");
|
||||||
|
stream << "class " << identifier << " (size: " << type->GetSize() << ")";
|
||||||
|
auto types = mapToVector(type->GetTypes());
|
||||||
|
for (size_t i = 0; i < types.size(); i++) {
|
||||||
|
stream << std::endl;
|
||||||
|
StringifyType(types[i].first, types[i].second, stream, prefix + (isLast ? " " : "│ "),
|
||||||
|
i == types.size() - 1);
|
||||||
|
}
|
||||||
|
auto fields = mapToVector(type->GetFieldsLookup());
|
||||||
|
for (size_t i = 0; i < fields.size(); i++) {
|
||||||
|
stream << std::endl;
|
||||||
|
StringifyField(fields[i].first, fields[i].second, stream, prefix + (isLast ? " " : "│ "),
|
||||||
|
i == fields.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void StringifyNamespace(const MalachScript::Identifier& identifier, const BoundNamespace* boundNamespace,
|
||||||
|
std::stringstream& stream, const std::string& prefix, bool isLast) {
|
||||||
|
stream << prefix;
|
||||||
|
stream << (isLast ? "└──" : "├──");
|
||||||
|
stream << "namespace " << identifier;
|
||||||
|
auto types = mapToVector(boundNamespace->GetTypes());
|
||||||
|
for (size_t i = 0; i < types.size(); i++) {
|
||||||
|
stream << std::endl;
|
||||||
|
StringifyType(types[i].first, types[i].second, stream, prefix + (isLast ? " " : "│ "),
|
||||||
|
i == types.size() - 1);
|
||||||
|
}
|
||||||
|
auto namespaces = mapToVector(boundNamespace->GetNamespaces());
|
||||||
|
for (size_t i = 0; i < namespaces.size(); i++) {
|
||||||
|
stream << std::endl;
|
||||||
|
StringifyNamespace(namespaces[i].first, namespaces[i].second, stream,
|
||||||
|
prefix + (isLast ? " " : "│ "), i == namespaces.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Stringify(const BoundNamespace* ns, std::stringstream& stream) {
|
||||||
|
StringifyNamespace("global"_id, ns, stream, "", true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MALACHSCRIPT_BOUNDNAMESPACESTRINGIFIER_HPP
|
|
@ -7,14 +7,31 @@
|
||||||
namespace MalachScript::Binder {
|
namespace MalachScript::Binder {
|
||||||
class BoundType {
|
class BoundType {
|
||||||
public:
|
public:
|
||||||
BoundType(ClassAttr classAttr) : _classAttr(classAttr) {}
|
BoundType(Identifier identifier, ClassAttr classAttr) : _identifier(identifier), _classAttr(classAttr) {}
|
||||||
BoundType(ClassAttr classAttr, size_t size) : _classAttr(classAttr), _size(size), _inherits(0) {}
|
BoundType(Identifier identifier, ClassAttr classAttr, size_t size)
|
||||||
|
: _identifier(identifier), _classAttr(classAttr), _size(size), _inherits(0) {}
|
||||||
|
|
||||||
inline void Finalise() noexcept {
|
inline void Finalise() noexcept {
|
||||||
|
if (_initialised) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_initialised = true;
|
_initialised = true;
|
||||||
// TODO: Calculate size
|
for (auto& inherits : _inherits) {
|
||||||
|
if (!inherits->IsInitialised()) {
|
||||||
|
const_cast<BoundType*>(inherits)->Finalise();
|
||||||
|
}
|
||||||
|
_size += inherits->GetSize();
|
||||||
|
}
|
||||||
|
for (auto& field : _fields) {
|
||||||
|
if (!field->GetType()->IsInitialised()) {
|
||||||
|
const_cast<BoundType*>(field->GetType())->Finalise();
|
||||||
|
}
|
||||||
|
_size += field->GetType()->GetSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] inline const Identifier& GetIdentifier() const noexcept { return _identifier; }
|
||||||
[[nodiscard]] inline size_t GetSize() const noexcept { return _size; }
|
[[nodiscard]] inline size_t GetSize() const noexcept { return _size; }
|
||||||
|
[[nodiscard]] inline bool IsInitialised() const noexcept { return _initialised; }
|
||||||
[[nodiscard]] inline ClassAttr GetAttributes() const noexcept { return _classAttr; }
|
[[nodiscard]] inline ClassAttr GetAttributes() const noexcept { return _classAttr; }
|
||||||
|
|
||||||
inline void AddInheritType(const BoundType* type) { _inherits.push_back(type); }
|
inline void AddInheritType(const BoundType* type) { _inherits.push_back(type); }
|
||||||
|
@ -27,8 +44,24 @@ namespace MalachScript::Binder {
|
||||||
_types[identifier] = const_cast<BoundType*>(type);
|
_types[identifier] = const_cast<BoundType*>(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline const std::unordered_map<Identifier, BoundType*>& GetTypes() const noexcept {
|
||||||
|
return _types;
|
||||||
|
}
|
||||||
|
[[nodiscard]] inline const std::unordered_map<Identifier, BoundVariable*>& GetFieldsLookup() const noexcept {
|
||||||
|
return _fieldsLookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::optional<BoundType*> ResolveType(const Identifier& identifier) const noexcept {
|
||||||
|
auto find = _types.find(identifier);
|
||||||
|
if (find == _types.end()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return find->second;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _initialised = false;
|
bool _initialised = false;
|
||||||
|
Identifier _identifier;
|
||||||
ClassAttr _classAttr;
|
ClassAttr _classAttr;
|
||||||
size_t _size = 0;
|
size_t _size = 0;
|
||||||
std::vector<const BoundType*> _inherits;
|
std::vector<const BoundType*> _inherits;
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace MalachScript {
|
||||||
uint32_t _hash;
|
uint32_t _hash;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Identifier() : _str(nullptr), _length(0), _hash(0) {}
|
Identifier() : _str(empty.c_str()), _length(0), _hash(0) {}
|
||||||
constexpr Identifier(const char* c) : _str(c), _length(CalcLength(c)), _hash(Hash(c)) {}
|
constexpr Identifier(const char* c) : _str(c), _length(CalcLength(c)), _hash(Hash(c)) {}
|
||||||
constexpr Identifier(const char* c, size_t length) : _str(c), _length(length), _hash(Hash(c)) {}
|
constexpr Identifier(const char* c, size_t length) : _str(c), _length(length), _hash(Hash(c)) {}
|
||||||
constexpr Identifier(const char* c, size_t length, uint32_t hash) : _str(c), _length(length), _hash(hash) {}
|
constexpr Identifier(const char* c, size_t length, uint32_t hash) : _str(c), _length(length), _hash(hash) {}
|
||||||
|
|
|
@ -27,17 +27,17 @@ namespace MalachScript {
|
||||||
|
|
||||||
static constinit Identifier _autoName = "auto";
|
static constinit Identifier _autoName = "auto";
|
||||||
|
|
||||||
static Binder::BoundType _int8Type = Binder::BoundType(ClassAttr::None, sizeof(int8_t));
|
static Binder::BoundType _int8Type = Binder::BoundType(_int8Name, ClassAttr::None, sizeof(int8_t));
|
||||||
static Binder::BoundType _int16Type = Binder::BoundType(ClassAttr::None, sizeof(int16_t));
|
static Binder::BoundType _int16Type = Binder::BoundType(_int16Name, ClassAttr::None, sizeof(int16_t));
|
||||||
static Binder::BoundType _int32Type = Binder::BoundType(ClassAttr::None, sizeof(int32_t));
|
static Binder::BoundType _int32Type = Binder::BoundType(_int32Name, ClassAttr::None, sizeof(int32_t));
|
||||||
static Binder::BoundType _int64Type = Binder::BoundType(ClassAttr::None, sizeof(int64_t));
|
static Binder::BoundType _int64Type = Binder::BoundType(_int64Name, ClassAttr::None, sizeof(int64_t));
|
||||||
static Binder::BoundType _uint8Type = Binder::BoundType(ClassAttr::None, sizeof(uint8_t));
|
static Binder::BoundType _uint8Type = Binder::BoundType(_uint8Name, ClassAttr::None, sizeof(uint8_t));
|
||||||
static Binder::BoundType _uint16Type = Binder::BoundType(ClassAttr::None, sizeof(uint16_t));
|
static Binder::BoundType _uint16Type = Binder::BoundType(_uint16Name, ClassAttr::None, sizeof(uint16_t));
|
||||||
static Binder::BoundType _uint32Type = Binder::BoundType(ClassAttr::None, sizeof(uint32_t));
|
static Binder::BoundType _uint32Type = Binder::BoundType(_uint32Name, ClassAttr::None, sizeof(uint32_t));
|
||||||
static Binder::BoundType _uint64Type = Binder::BoundType(ClassAttr::None, sizeof(uint64_t));
|
static Binder::BoundType _uint64Type = Binder::BoundType(_uint64Name, ClassAttr::None, sizeof(uint64_t));
|
||||||
static Binder::BoundType _floatType = Binder::BoundType(ClassAttr::None, sizeof(float));
|
static Binder::BoundType _floatType = Binder::BoundType(_floatName, ClassAttr::None, sizeof(float));
|
||||||
static Binder::BoundType _doubleType = Binder::BoundType(ClassAttr::None, sizeof(double));
|
static Binder::BoundType _doubleType = Binder::BoundType(_doubleName, ClassAttr::None, sizeof(double));
|
||||||
static Binder::BoundType _boolType = Binder::BoundType(ClassAttr::None, sizeof(uint8_t));
|
static Binder::BoundType _boolType = Binder::BoundType(_boolName, ClassAttr::None, sizeof(uint8_t));
|
||||||
|
|
||||||
class PrimitiveTypes {
|
class PrimitiveTypes {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace MalachScript::Diagnostics {
|
||||||
DoubleProperty,
|
DoubleProperty,
|
||||||
|
|
||||||
UnknownType,
|
UnknownType,
|
||||||
|
TypeAlreadyDefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,10 @@ namespace MalachScript::Diagnostics {
|
||||||
}
|
}
|
||||||
case DiagnosticType::DoubleProperty: return "Property block found twice.";
|
case DiagnosticType::DoubleProperty: return "Property block found twice.";
|
||||||
|
|
||||||
case DiagnosticType::UnknownType: util::Format("Unknown Type Encounted: '{0}'", diag->GetFormats());
|
case DiagnosticType::UnknownType:
|
||||||
|
return util::Format("Unknown Type Encounted: '{0}'", diag->GetFormats());
|
||||||
|
case DiagnosticType::TypeAlreadyDefined:
|
||||||
|
return util::Format("Type already defined: '{0}'", diag->GetFormats());
|
||||||
}
|
}
|
||||||
return std::to_string((uint8_t)diag->GetType());
|
return std::to_string((uint8_t)diag->GetType());
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,8 @@ namespace MalachScript::Parser {
|
||||||
ScopedPtr<const ParsedStatement> statement = nullptr;
|
ScopedPtr<const ParsedStatement> statement = nullptr;
|
||||||
// TODO: Sort by complexity
|
// TODO: Sort by complexity
|
||||||
if (!ParseVirtProp(statement, current, log) && !ParseFunc(statement, current, log) &&
|
if (!ParseVirtProp(statement, current, log) && !ParseFunc(statement, current, log) &&
|
||||||
!ParseVar(statement, current, log) && !ParseFuncDef(statement, current, log)) {
|
!ParseVar(statement, current, log) && !ParseFuncDef(statement, current, log) &&
|
||||||
|
!ParseClass(statement, current, log)) {
|
||||||
logUnexpectedTokenWithoutExpected(current);
|
logUnexpectedTokenWithoutExpected(current);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
#ifndef MALACHSCRIPT_TREEPRINTER_HPP
|
|
||||||
#define MALACHSCRIPT_TREEPRINTER_HPP
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
class MalachScript::Utils {
|
|
||||||
class TreePrinter {
|
|
||||||
public:
|
|
||||||
private:
|
|
||||||
std::stringstream _stream;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MALACHSCRIPT_TREEPRINTER_HPP
|
|
Loading…
Reference in New Issue