Implement a simpler error model
This commit is contained in:
parent
b1cca14433
commit
9d894b662b
|
@ -185,11 +185,11 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
add_definitions(${LLVM_DEFINITIONS})
|
add_definitions(${LLVM_DEFINITIONS})
|
||||||
|
|
||||||
# /LLVM setup =================================================================
|
# /LLVM setup =================================================================
|
||||||
|
#add_subdirectory(serene-tblgen)
|
||||||
add_subdirectory(serene)
|
add_subdirectory(serene)
|
||||||
# include(tablegen-serene)
|
# include(tablegen-serene)
|
||||||
# Create the tools we use to compile Serene
|
# Create the tools we use to compile Serene
|
||||||
#add_subdirectory(serene-tblgen)
|
|
||||||
# The compiled library code is here
|
# The compiled library code is here
|
||||||
# add_subdirectory(libserene)
|
# add_subdirectory(libserene)
|
||||||
# The static library containing builtin special forms and functions
|
# The static library containing builtin special forms and functions
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/serene-tblgen)
|
|
||||||
|
|
||||||
add_executable(serene-tblgen
|
add_executable(serene-tblgen
|
||||||
serene/errors-backend.cpp
|
serene/errors-backend.cpp
|
||||||
|
@ -28,8 +27,10 @@ set(SERENE_TABLEGEN $<TARGET_FILE:serene-tblgen> CACHE
|
||||||
|
|
||||||
set(SERENE_TABLEGEN_EXE SereneTablegen
|
set(SERENE_TABLEGEN_EXE SereneTablegen
|
||||||
CACHE STRING "Where to find the tbl-srn binary")
|
CACHE STRING "Where to find the tbl-srn binary")
|
||||||
|
|
||||||
set(SERENE_TABLEGEN_TARGET SereneTablegen CACHE
|
set(SERENE_TABLEGEN_TARGET SereneTablegen CACHE
|
||||||
STRING "Target name for the tbl-srn")
|
STRING "Target name for the tbl-srn")
|
||||||
|
|
||||||
target_link_libraries(serene-tblgen PRIVATE LLVMTableGenGlobalISel ${llvm_libs})
|
target_link_libraries(serene-tblgen PRIVATE LLVMTableGenGlobalISel ${llvm_libs})
|
||||||
|
target_include_directories(${PROJECT_SOURCE_DIR}/serene-tblgen)
|
||||||
set_target_properties(serene-tblgen PROPERTIES FOLDER "serene-tblgen")
|
set_target_properties(serene-tblgen PROPERTIES FOLDER "serene-tblgen")
|
||||||
|
|
|
@ -20,6 +20,7 @@ target_sources(serene PRIVATE
|
||||||
commands/commands.cpp
|
commands/commands.cpp
|
||||||
jit/jit.cpp
|
jit/jit.cpp
|
||||||
|
|
||||||
|
errors.cpp
|
||||||
ast.cpp
|
ast.cpp
|
||||||
namespace.cpp
|
namespace.cpp
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene Programming Language
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2023 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ERRORS_H
|
||||||
|
#define _ERRORS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// TODO: Autogenerate this file
|
||||||
|
|
||||||
|
namespace serene::errors {
|
||||||
|
enum class Type {
|
||||||
|
NSLoadError = 0,
|
||||||
|
NSAddToSMError,
|
||||||
|
InvalidDigitForNumber,
|
||||||
|
TwoFloatPoints,
|
||||||
|
InvalidCharacterForSymbol,
|
||||||
|
EOFWhileScaningAList,
|
||||||
|
// This error has to be the final error at all time. DO NOT CHANGE IT!
|
||||||
|
FINALERROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::string errorMessages[static_cast<int>(Type::FINALERROR) + 1] = {
|
||||||
|
"Faild to load the namespace", // NSLoadError
|
||||||
|
"Faild to add the namespace to the source manager", // NSAddToSMError
|
||||||
|
"Invalid number format", // InvalidDigitForNumber
|
||||||
|
"Invalid float number format", // TwoFloatPoints,
|
||||||
|
"Invalid symbol format", // InvalidCharacterForSymbol
|
||||||
|
"Reached the end of the file while scanning for a list", // EOFWhileScaningAList
|
||||||
|
};
|
||||||
|
} // namespace serene::errors
|
||||||
|
#endif
|
|
@ -104,6 +104,7 @@ bool List::classof(const Expression *e) {
|
||||||
return e->getType() == TypeID::LIST;
|
return e->getType() == TypeID::LIST;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void List::append(Node &n) { elements.push_back(std::move(n)); }
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// String
|
// String
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
|
@ -134,6 +134,7 @@ struct List : public Expression {
|
||||||
std::string toString() const override;
|
std::string toString() const override;
|
||||||
|
|
||||||
~List() = default;
|
~List() = default;
|
||||||
|
void append(Node &n);
|
||||||
|
|
||||||
static bool classof(const Expression *e);
|
static bool classof(const Expression *e);
|
||||||
};
|
};
|
||||||
|
@ -221,7 +222,7 @@ Node make(Args &&...args) {
|
||||||
/// passed to the constructor of type T.
|
/// passed to the constructor of type T.
|
||||||
/// \return A unique pointer to a value of type T.
|
/// \return A unique pointer to a value of type T.
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
std::shared_ptr<T> makeAndCast(Args &&...args) {
|
std::unique_ptr<T> makeAndCast(Args &&...args) {
|
||||||
return std::make_unique<T>(std::forward<Args>(args)...);
|
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene Programming Language
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2023 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "errors.h"
|
||||||
|
|
||||||
|
#include <llvm/Support/Casting.h>
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
|
|
||||||
|
namespace serene::errors {
|
||||||
|
|
||||||
|
// We need this to make Error class a llvm::Error friendy implementation
|
||||||
|
char Error::ID;
|
||||||
|
|
||||||
|
std::string getMessage(const llvm::Error &e) {
|
||||||
|
std::string msg;
|
||||||
|
llvm::raw_string_ostream os(msg);
|
||||||
|
os << e;
|
||||||
|
return os.str();
|
||||||
|
};
|
||||||
|
} // namespace serene::errors
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene Programming Language
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2023 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ERRORS_H
|
||||||
|
#define ERRORS_H
|
||||||
|
|
||||||
|
#include "_errors.h"
|
||||||
|
#include "location.h"
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
|
#include <llvm/Support/FormatVariadic.h>
|
||||||
|
|
||||||
|
namespace serene::errors {
|
||||||
|
|
||||||
|
class Error : public llvm::ErrorInfo<Error> {
|
||||||
|
public:
|
||||||
|
// We need this to make Error class a llvm::Error friendy implementation
|
||||||
|
static char ID;
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
LocationRange location;
|
||||||
|
std::string msg;
|
||||||
|
|
||||||
|
void log(llvm::raw_ostream &os) const override { os << msg; }
|
||||||
|
|
||||||
|
std::error_code convertToErrorCode() const override {
|
||||||
|
// TODO: Fix this by creating a mapping from ErrorType to standard
|
||||||
|
// errc or return the ErrorType number instead
|
||||||
|
return std::make_error_code(std::errc::io_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error(Type errtype, LocationRange &loc) : type(errtype), location(loc){};
|
||||||
|
|
||||||
|
Error(Type errtype, LocationRange &loc, llvm::StringRef msg)
|
||||||
|
: type(errtype), location(loc), msg(msg.str()){};
|
||||||
|
|
||||||
|
LocationRange &where() { return location; };
|
||||||
|
};
|
||||||
|
|
||||||
|
llvm::Error make(Type t, LocationRange &loc, llvm::StringRef msg) {
|
||||||
|
return llvm::make_error<Error>(t, loc, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Error make(Type t, LocationRange &loc) {
|
||||||
|
return llvm::make_error<Error>(t, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace serene::errors
|
||||||
|
#endif
|
|
@ -18,7 +18,9 @@
|
||||||
|
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
|
|
||||||
// #include "serene/errors.h"
|
#include "errors.h"
|
||||||
|
#include "jit/jit.h"
|
||||||
|
#include "utils.h"
|
||||||
// #include "serene/exprs/expression.h"
|
// #include "serene/exprs/expression.h"
|
||||||
// #include "serene/exprs/list.h"
|
// #include "serene/exprs/list.h"
|
||||||
// #include "serene/exprs/number.h"
|
// #include "serene/exprs/number.h"
|
||||||
|
@ -46,7 +48,6 @@
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
|
||||||
namespace reader {
|
|
||||||
// LocationRange::LocationRange(const LocationRange &loc) {
|
// LocationRange::LocationRange(const LocationRange &loc) {
|
||||||
// start = loc.start.clone();
|
// start = loc.start.clone();
|
||||||
// end = loc.end.clone();
|
// end = loc.end.clone();
|
||||||
|
@ -98,11 +99,11 @@ void decLocation(Location &loc, const char *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reader::Reader(SereneContext &ctx, llvm::StringRef buffer, llvm::StringRef ns,
|
Reader::Reader(jit::JIT &engine, llvm::StringRef buffer, llvm::StringRef ns,
|
||||||
std::optional<llvm::StringRef> filename)
|
std::optional<llvm::StringRef> filename)
|
||||||
: ctx(ctx), ns(ns), filename(filename), buf(buffer),
|
: engine(engine), ns(ns), filename(filename), buf(buffer),
|
||||||
currentLocation(Location(ns, filename)) {
|
currentLocation(Location(ns, filename)) {
|
||||||
UNUSED(this->ctx);
|
UNUSED(this->engine);
|
||||||
READER_LOG("Setting the first char of the buffer");
|
READER_LOG("Setting the first char of the buffer");
|
||||||
currentChar = buf.begin() - 1;
|
currentChar = buf.begin() - 1;
|
||||||
currentPos = 1;
|
currentPos = 1;
|
||||||
|
@ -110,9 +111,9 @@ Reader::Reader(SereneContext &ctx, llvm::StringRef buffer, llvm::StringRef ns,
|
||||||
currentLocation.col = 1;
|
currentLocation.col = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
Reader::Reader(SereneContext &ctx, llvm::MemoryBufferRef buffer,
|
Reader::Reader(jit::JIT &engine, llvm::MemoryBufferRef buffer,
|
||||||
llvm::StringRef ns, std::optional<llvm::StringRef> filename)
|
llvm::StringRef ns, std::optional<llvm::StringRef> filename)
|
||||||
: Reader(ctx, buffer.getBuffer(), ns, filename){};
|
: Reader(engine, buffer.getBuffer(), ns, filename){};
|
||||||
|
|
||||||
Reader::~Reader() { READER_LOG("Destroying the reader"); }
|
Reader::~Reader() { READER_LOG("Destroying the reader"); }
|
||||||
|
|
||||||
|
@ -173,7 +174,8 @@ const char *Reader::nextChar(bool skipWhitespace, unsigned count) {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Reader::isEndOfBuffer(const char *c) {
|
bool Reader::isEndOfBuffer(const char *c) {
|
||||||
return *c == '\0' || currentPos > buf.size() || ((const int)*c == EOF);
|
return *c == '\0' || currentPos > buf.size() ||
|
||||||
|
(static_cast<const int>(*c) == EOF);
|
||||||
};
|
};
|
||||||
|
|
||||||
Location Reader::getCurrentLocation() { return currentLocation.clone(); };
|
Location Reader::getCurrentLocation() { return currentLocation.clone(); };
|
||||||
|
@ -208,7 +210,7 @@ bool Reader::isValidForIdentifier(char c) {
|
||||||
|
|
||||||
/// Reads a number,
|
/// Reads a number,
|
||||||
/// \param neg whether to read a negative number or not.
|
/// \param neg whether to read a negative number or not.
|
||||||
exprs::MaybeNode Reader::readNumber(bool neg) {
|
ast::MaybeNode Reader::readNumber(bool neg) {
|
||||||
READER_LOG("Reading a number...");
|
READER_LOG("Reading a number...");
|
||||||
std::string number(neg ? "-" : "");
|
std::string number(neg ? "-" : "");
|
||||||
bool floatNum = false;
|
bool floatNum = false;
|
||||||
|
@ -220,7 +222,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
|
||||||
LocationRange loc(getCurrentLocation());
|
LocationRange loc(getCurrentLocation());
|
||||||
|
|
||||||
if (isdigit(*c) == 0) {
|
if (isdigit(*c) == 0) {
|
||||||
return errors::makeError(ctx, errors::InvalidDigitForNumber, loc);
|
return errors::make(errors::Type::InvalidDigitForNumber, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -231,7 +233,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
|
||||||
if ((isdigit(*c) != 0) || *c == '.') {
|
if ((isdigit(*c) != 0) || *c == '.') {
|
||||||
if (*c == '.' && floatNum) {
|
if (*c == '.' && floatNum) {
|
||||||
loc = LocationRange(getCurrentLocation());
|
loc = LocationRange(getCurrentLocation());
|
||||||
return errors::makeError(ctx, errors::TwoFloatPoints, loc);
|
return errors::make(errors::Type::TwoFloatPoints, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*c == '.') {
|
if (*c == '.') {
|
||||||
|
@ -247,16 +249,16 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
|
||||||
if (((std::isalpha(*c) != 0) && !empty) || empty) {
|
if (((std::isalpha(*c) != 0) && !empty) || empty) {
|
||||||
advance();
|
advance();
|
||||||
loc.start = getCurrentLocation();
|
loc.start = getCurrentLocation();
|
||||||
return errors::makeError(ctx, errors::InvalidDigitForNumber, loc);
|
return errors::make(errors::Type::InvalidDigitForNumber, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
loc.end = getCurrentLocation();
|
loc.end = getCurrentLocation();
|
||||||
return exprs::make<exprs::Number>(loc, number, neg, floatNum);
|
return ast::make<ast::Number>(loc, number, neg, floatNum);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reads a symbol. If the symbol looks like a number
|
/// Reads a symbol. If the symbol looks like a number
|
||||||
/// If reads it as number
|
/// If reads it as number
|
||||||
exprs::MaybeNode Reader::readSymbol() {
|
ast::MaybeNode Reader::readSymbol() {
|
||||||
READER_LOG("Reading a symbol...");
|
READER_LOG("Reading a symbol...");
|
||||||
LocationRange loc;
|
LocationRange loc;
|
||||||
const auto *c = nextChar();
|
const auto *c = nextChar();
|
||||||
|
@ -271,7 +273,7 @@ exprs::MaybeNode Reader::readSymbol() {
|
||||||
msg = "An extra ')' is detected.";
|
msg = "An extra ')' is detected.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors::makeError(ctx, errors::InvalidCharacterForSymbol, loc, msg);
|
return errors::make(errors::Type::InvalidCharacterForSymbol, loc, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*c == '-') {
|
if (*c == '-') {
|
||||||
|
@ -307,17 +309,17 @@ exprs::MaybeNode Reader::readSymbol() {
|
||||||
// TODO: Make sure that `/` is not at the start or at the end of the symbol
|
// TODO: Make sure that `/` is not at the start or at the end of the symbol
|
||||||
|
|
||||||
loc.end = getCurrentLocation();
|
loc.end = getCurrentLocation();
|
||||||
return exprs::makeSuccessfulNode<exprs::Symbol>(loc, sym, this->ns);
|
return ast::makeSuccessfulNode<ast::Symbol>(loc, sym, this->ns);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reads a list recursively
|
/// Reads a list recursively
|
||||||
exprs::MaybeNode Reader::readList() {
|
ast::MaybeNode Reader::readList() {
|
||||||
READER_LOG("Reading a list...");
|
READER_LOG("Reading a list...");
|
||||||
|
|
||||||
const auto *c = nextChar();
|
const auto *c = nextChar();
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
auto list = exprs::makeAndCast<exprs::List>(getCurrentLocation());
|
auto list = ast::makeAndCast<ast::List>(getCurrentLocation());
|
||||||
|
|
||||||
// TODO: Replace the assert with an actual check.
|
// TODO: Replace the assert with an actual check.
|
||||||
assert(*c == '(');
|
assert(*c == '(');
|
||||||
|
@ -331,8 +333,7 @@ exprs::MaybeNode Reader::readList() {
|
||||||
advance(true);
|
advance(true);
|
||||||
advance();
|
advance();
|
||||||
list->location.end = getCurrentLocation();
|
list->location.end = getCurrentLocation();
|
||||||
return errors::makeError(ctx, errors::EOFWhileScaningAList,
|
return errors::make(errors::Type::EOFWhileScaningAList, list->location);
|
||||||
list->location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*c) {
|
switch (*c) {
|
||||||
|
@ -359,13 +360,13 @@ exprs::MaybeNode Reader::readList() {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reads an expression by dispatching to the proper reader function.
|
/// Reads an expression by dispatching to the proper reader function.
|
||||||
exprs::MaybeNode Reader::readExpr() {
|
ast::MaybeNode Reader::readExpr() {
|
||||||
const auto *c = nextChar(true);
|
const auto *c = nextChar(true);
|
||||||
|
|
||||||
READER_LOG("Read char at `readExpr`: " << *c);
|
READER_LOG("Read char at `readExpr`: " << *c);
|
||||||
|
|
||||||
if (isEndOfBuffer(c)) {
|
if (isEndOfBuffer(c)) {
|
||||||
return exprs::EmptyNode;
|
return ast::EmptyNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*c) {
|
switch (*c) {
|
||||||
|
@ -383,7 +384,7 @@ exprs::MaybeNode Reader::readExpr() {
|
||||||
/// Reads all the expressions in the reader's buffer as an AST.
|
/// Reads all the expressions in the reader's buffer as an AST.
|
||||||
/// Each expression type (from the reader perspective) has a
|
/// Each expression type (from the reader perspective) has a
|
||||||
/// reader function.
|
/// reader function.
|
||||||
exprs::MaybeAst Reader::read() {
|
ast::MaybeAst Reader::read() {
|
||||||
|
|
||||||
for (size_t current_pos = 0; current_pos < buf.size();) {
|
for (size_t current_pos = 0; current_pos < buf.size();) {
|
||||||
const auto *c = nextChar(true);
|
const auto *c = nextChar(true);
|
||||||
|
@ -411,21 +412,21 @@ exprs::MaybeAst Reader::read() {
|
||||||
return std::move(this->ast);
|
return std::move(this->ast);
|
||||||
};
|
};
|
||||||
|
|
||||||
exprs::MaybeAst read(SereneContext &ctx, const llvm::StringRef input,
|
ast::MaybeAst read(jit::JIT &engine, const llvm::StringRef input,
|
||||||
llvm::StringRef ns,
|
llvm::StringRef ns,
|
||||||
std::optional<llvm::StringRef> filename) {
|
std::optional<llvm::StringRef> filename) {
|
||||||
reader::Reader r(ctx, input, ns, filename);
|
Reader r(engine, input, ns, filename);
|
||||||
auto ast = r.read();
|
auto ast = r.read();
|
||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
exprs::MaybeAst read(SereneContext &ctx, const llvm::MemoryBufferRef input,
|
ast::MaybeAst read(jit::JIT &engine, const llvm::MemoryBufferRef input,
|
||||||
llvm::StringRef ns,
|
llvm::StringRef ns,
|
||||||
std::optional<llvm::StringRef> filename) {
|
std::optional<llvm::StringRef> filename) {
|
||||||
reader::Reader r(ctx, input, ns, filename);
|
Reader r(engine, input, ns, filename);
|
||||||
|
|
||||||
auto ast = r.read();
|
auto ast = r.read();
|
||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
} // namespace reader
|
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -43,10 +43,19 @@
|
||||||
#include <llvm/ADT/StringRef.h>
|
#include <llvm/ADT/StringRef.h>
|
||||||
#include <llvm/Support/MemoryBufferRef.h>
|
#include <llvm/Support/MemoryBufferRef.h>
|
||||||
|
|
||||||
|
#define READER_LOG(...) \
|
||||||
|
DEBUG_WITH_TYPE("READER", llvm::dbgs() \
|
||||||
|
<< "[READER]: " << __VA_ARGS__ << "\n");
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
namespace jit {
|
||||||
|
class JIT;
|
||||||
|
} // namespace jit
|
||||||
|
|
||||||
/// Base reader class which reads from a string directly.
|
/// Base reader class which reads from a string directly.
|
||||||
class Reader {
|
class Reader {
|
||||||
private:
|
private:
|
||||||
|
jit::JIT &engine;
|
||||||
llvm::StringRef ns;
|
llvm::StringRef ns;
|
||||||
std::optional<llvm::StringRef> filename;
|
std::optional<llvm::StringRef> filename;
|
||||||
|
|
||||||
|
@ -77,35 +86,35 @@ private:
|
||||||
static bool isValidForIdentifier(char c);
|
static bool isValidForIdentifier(char c);
|
||||||
|
|
||||||
// The property to store the ast tree
|
// The property to store the ast tree
|
||||||
Ast ast;
|
ast::Ast ast;
|
||||||
|
|
||||||
MaybeNode readSymbol();
|
ast::MaybeNode readSymbol();
|
||||||
MaybeNode readNumber(bool);
|
ast::MaybeNode readNumber(bool);
|
||||||
MaybeNode readList();
|
ast::MaybeNode readList();
|
||||||
MaybeNode readExpr();
|
ast::MaybeNode readExpr();
|
||||||
|
|
||||||
bool isEndOfBuffer(const char *);
|
bool isEndOfBuffer(const char *);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Reader(llvm::StringRef buf, llvm::StringRef ns,
|
Reader(jit::JIT &engine, llvm::StringRef buf, llvm::StringRef ns,
|
||||||
std::optional<llvm::StringRef> filename);
|
std::optional<llvm::StringRef> filename);
|
||||||
Reader(llvm::MemoryBufferRef buf, llvm::StringRef ns,
|
Reader(jit::JIT &engine, llvm::MemoryBufferRef buf, llvm::StringRef ns,
|
||||||
std::optional<llvm::StringRef> filename);
|
std::optional<llvm::StringRef> filename);
|
||||||
|
|
||||||
// void setInput(const llvm::StringRef string);
|
// void setInput(const llvm::StringRef string);
|
||||||
|
|
||||||
/// Parses the the input and creates a possible AST out of it or errors
|
/// Parses the the input and creates a possible AST out of it or errors
|
||||||
/// otherwise.
|
/// otherwise.
|
||||||
MaybeAst read();
|
ast::MaybeAst read();
|
||||||
|
|
||||||
~Reader();
|
~Reader();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses the given `input` string and returns a `Result<ast>`
|
/// Parses the given `input` string and returns a `Result<ast>`
|
||||||
/// which may contains an AST or an `llvm::Error`
|
/// which may contains an AST or an `llvm::Error`
|
||||||
MaybeAst read(llvm::StringRef input, llvm::StringRef ns,
|
ast::MaybeAst read(llvm::StringRef input, llvm::StringRef ns,
|
||||||
std::optional<llvm::StringRef> filename);
|
std::optional<llvm::StringRef> filename);
|
||||||
MaybeAst read(llvm::MemoryBufferRef input, llvm::StringRef ns,
|
ast::MaybeAst read(llvm::MemoryBufferRef input, llvm::StringRef ns,
|
||||||
std::optional<llvm::StringRef> filename);
|
std::optional<llvm::StringRef> filename);
|
||||||
|
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -16,12 +16,13 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "serene/source_mgr.h"
|
#include "source_mgr.h"
|
||||||
|
|
||||||
#include "serene/namespace.h"
|
#include "errors.h"
|
||||||
#include "serene/reader/location.h"
|
#include "jit/jit.h"
|
||||||
#include "serene/reader/reader.h"
|
#include "location.h"
|
||||||
#include "serene/utils.h"
|
#include "reader.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
|
@ -75,8 +76,8 @@ SourceMgr::MemBufPtr SourceMgr::findFileInLoadPath(const std::string &name,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
MaybeNS SourceMgr::readNamespace(jit::JIT &engine, std::string name,
|
||||||
reader::LocationRange importLoc) {
|
LocationRange importLoc) {
|
||||||
std::string importedFile;
|
std::string importedFile;
|
||||||
|
|
||||||
SMGR_LOG("Attempt to load namespace: " + name);
|
SMGR_LOG("Attempt to load namespace: " + name);
|
||||||
|
@ -84,7 +85,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
|
|
||||||
if (newBufOrErr == nullptr) {
|
if (newBufOrErr == nullptr) {
|
||||||
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name).str();
|
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name).str();
|
||||||
return errors::makeError(ctx, errors::NSLoadError, importLoc, msg);
|
return errors::make(errors::Type::NSLoadError, importLoc, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bufferId = AddNewSourceBuffer(std::move(newBufOrErr), importLoc);
|
auto bufferId = AddNewSourceBuffer(std::move(newBufOrErr), importLoc);
|
||||||
|
@ -93,7 +94,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
|
|
||||||
if (bufferId == 0) {
|
if (bufferId == 0) {
|
||||||
auto msg = llvm::formatv("Couldn't add namespace '{0}'", name).str();
|
auto msg = llvm::formatv("Couldn't add namespace '{0}'", name).str();
|
||||||
return errors::makeError(ctx, errors::NSAddToSMError, importLoc, msg);
|
return errors::make(errors::Type; : NSAddToSMError, importLoc, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we moved the buffer to be added as the source storage we
|
// Since we moved the buffer to be added as the source storage we
|
||||||
|
@ -101,7 +102,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
const auto *buf = getMemoryBuffer(bufferId);
|
const auto *buf = getMemoryBuffer(bufferId);
|
||||||
|
|
||||||
// Read the content of the buffer by passing it the reader
|
// Read the content of the buffer by passing it the reader
|
||||||
auto maybeAst = reader::read(ctx, buf->getBuffer(), name,
|
auto maybeAst = read(jit, buf->getBuffer(), name,
|
||||||
std::optional(llvm::StringRef(importedFile)));
|
std::optional(llvm::StringRef(importedFile)));
|
||||||
|
|
||||||
if (!maybeAst) {
|
if (!maybeAst) {
|
||||||
|
@ -111,7 +112,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
|
|
||||||
// Create the NS and set the AST
|
// Create the NS and set the AST
|
||||||
auto ns =
|
auto ns =
|
||||||
ctx.makeNamespace(name, std::optional(llvm::StringRef(importedFile)));
|
engine.makeNamespace(name, std::optional(llvm::StringRef(importedFile)));
|
||||||
|
|
||||||
if (auto errs = ns->addTree(*maybeAst)) {
|
if (auto errs = ns->addTree(*maybeAst)) {
|
||||||
SMGR_LOG("Couldn't set the AST for namespace: " + name);
|
SMGR_LOG("Couldn't set the AST for namespace: " + name);
|
||||||
|
@ -122,7 +123,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned SourceMgr::AddNewSourceBuffer(std::unique_ptr<llvm::MemoryBuffer> f,
|
unsigned SourceMgr::AddNewSourceBuffer(std::unique_ptr<llvm::MemoryBuffer> f,
|
||||||
reader::LocationRange includeLoc) {
|
LocationRange includeLoc) {
|
||||||
SrcBuffer nb;
|
SrcBuffer nb;
|
||||||
nb.buffer = std::move(f);
|
nb.buffer = std::move(f);
|
||||||
nb.importLoc = includeLoc;
|
nb.importLoc = includeLoc;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define SERENE_SOURCE_MGR_H
|
#define SERENE_SOURCE_MGR_H
|
||||||
|
|
||||||
#include "location.h"
|
#include "location.h"
|
||||||
|
#include "namespace.h"
|
||||||
|
|
||||||
#include <llvm/ADT/SmallVector.h>
|
#include <llvm/ADT/SmallVector.h>
|
||||||
#include <llvm/ADT/StringMap.h>
|
#include <llvm/ADT/StringMap.h>
|
||||||
|
@ -38,7 +39,9 @@
|
||||||
<< "[SMGR]: " << __VA_ARGS__ << "\n");
|
<< "[SMGR]: " << __VA_ARGS__ << "\n");
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
class SereneContext;
|
namespace jit {
|
||||||
|
class JIT;
|
||||||
|
} // namespace jit
|
||||||
|
|
||||||
/// This class is quite similar to the `llvm::SourceMgr` in functionality. We
|
/// This class is quite similar to the `llvm::SourceMgr` in functionality. We
|
||||||
/// even borrowed some of the code from the original implementation but removed
|
/// even borrowed some of the code from the original implementation but removed
|
||||||
|
@ -181,7 +184,7 @@ public:
|
||||||
///
|
///
|
||||||
/// \p importLoc is a location in the source code where the give namespace is
|
/// \p importLoc is a location in the source code where the give namespace is
|
||||||
/// imported.
|
/// imported.
|
||||||
MaybeNS readNamespace(SereneContext &ctx, std::string name,
|
MaybeNS readNamespace(jit::JIT &engine, std::string name,
|
||||||
LocationRange importLoc);
|
LocationRange importLoc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue