diff --git a/CMakeLists.txt b/CMakeLists.txt
index 483c1c7..a90c84c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -185,11 +185,11 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
add_definitions(${LLVM_DEFINITIONS})
# /LLVM setup =================================================================
-
+ #add_subdirectory(serene-tblgen)
add_subdirectory(serene)
# include(tablegen-serene)
# Create the tools we use to compile Serene
- #add_subdirectory(serene-tblgen)
+
# The compiled library code is here
# add_subdirectory(libserene)
# The static library containing builtin special forms and functions
diff --git a/serene-tblgen/CMakeLists.txt b/serene-tblgen/CMakeLists.txt
index 0f1f913..987e3b6 100644
--- a/serene-tblgen/CMakeLists.txt
+++ b/serene-tblgen/CMakeLists.txt
@@ -14,7 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-include_directories(${PROJECT_SOURCE_DIR}/serene-tblgen)
add_executable(serene-tblgen
serene/errors-backend.cpp
@@ -28,8 +27,10 @@ set(SERENE_TABLEGEN $ CACHE
set(SERENE_TABLEGEN_EXE SereneTablegen
CACHE STRING "Where to find the tbl-srn binary")
+
set(SERENE_TABLEGEN_TARGET SereneTablegen CACHE
STRING "Target name for the tbl-srn")
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")
diff --git a/serene/src/CMakeLists.txt b/serene/src/CMakeLists.txt
index c544c98..f261139 100644
--- a/serene/src/CMakeLists.txt
+++ b/serene/src/CMakeLists.txt
@@ -20,6 +20,7 @@ target_sources(serene PRIVATE
commands/commands.cpp
jit/jit.cpp
+ errors.cpp
ast.cpp
namespace.cpp
diff --git a/serene/src/_errors.h b/serene/src/_errors.h
new file mode 100644
index 0000000..9f2ae74
--- /dev/null
+++ b/serene/src/_errors.h
@@ -0,0 +1,47 @@
+/* -*- C++ -*-
+ * Serene Programming Language
+ *
+ * Copyright (c) 2019-2023 Sameer Rahmani
+ *
+ * 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 .
+ */
+
+#ifndef _ERRORS_H
+#define _ERRORS_H
+
+#include
+
+// 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(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
diff --git a/serene/src/ast.cpp b/serene/src/ast.cpp
index d445b26..6019f0d 100644
--- a/serene/src/ast.cpp
+++ b/serene/src/ast.cpp
@@ -104,6 +104,7 @@ bool List::classof(const Expression *e) {
return e->getType() == TypeID::LIST;
};
+void List::append(Node &n) { elements.push_back(std::move(n)); }
// ============================================================================
// String
// ============================================================================
diff --git a/serene/src/ast.h b/serene/src/ast.h
index a39d62e..3a6f493 100644
--- a/serene/src/ast.h
+++ b/serene/src/ast.h
@@ -134,6 +134,7 @@ struct List : public Expression {
std::string toString() const override;
~List() = default;
+ void append(Node &n);
static bool classof(const Expression *e);
};
@@ -221,7 +222,7 @@ Node make(Args &&...args) {
/// passed to the constructor of type T.
/// \return A unique pointer to a value of type T.
template
-std::shared_ptr makeAndCast(Args &&...args) {
+std::unique_ptr makeAndCast(Args &&...args) {
return std::make_unique(std::forward(args)...);
};
diff --git a/serene/src/errors.cpp b/serene/src/errors.cpp
new file mode 100644
index 0000000..3995ca6
--- /dev/null
+++ b/serene/src/errors.cpp
@@ -0,0 +1,35 @@
+/* -*- C++ -*-
+ * Serene Programming Language
+ *
+ * Copyright (c) 2019-2023 Sameer Rahmani
+ *
+ * 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 .
+ */
+
+#include "errors.h"
+
+#include
+#include
+
+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
diff --git a/serene/src/errors.h b/serene/src/errors.h
new file mode 100644
index 0000000..0dea5b1
--- /dev/null
+++ b/serene/src/errors.h
@@ -0,0 +1,66 @@
+/* -*- C++ -*-
+ * Serene Programming Language
+ *
+ * Copyright (c) 2019-2023 Sameer Rahmani
+ *
+ * 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 .
+ */
+
+#ifndef ERRORS_H
+#define ERRORS_H
+
+#include "_errors.h"
+#include "location.h"
+
+#include
+
+#include
+#include
+
+namespace serene::errors {
+
+class Error : public llvm::ErrorInfo {
+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(t, loc, msg);
+}
+
+llvm::Error make(Type t, LocationRange &loc) {
+ return llvm::make_error(t, loc);
+}
+
+}; // namespace serene::errors
+#endif
diff --git a/serene/src/reader.cpp b/serene/src/reader.cpp
index 8087b2b..f55c72d 100644
--- a/serene/src/reader.cpp
+++ b/serene/src/reader.cpp
@@ -18,7 +18,9 @@
#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/list.h"
// #include "serene/exprs/number.h"
@@ -46,7 +48,6 @@
namespace serene {
-namespace reader {
// LocationRange::LocationRange(const LocationRange &loc) {
// start = loc.start.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 filename)
- : ctx(ctx), ns(ns), filename(filename), buf(buffer),
+ : engine(engine), ns(ns), filename(filename), buf(buffer),
currentLocation(Location(ns, filename)) {
- UNUSED(this->ctx);
+ UNUSED(this->engine);
READER_LOG("Setting the first char of the buffer");
currentChar = buf.begin() - 1;
currentPos = 1;
@@ -110,9 +111,9 @@ Reader::Reader(SereneContext &ctx, llvm::StringRef buffer, llvm::StringRef ns,
currentLocation.col = 1;
};
-Reader::Reader(SereneContext &ctx, llvm::MemoryBufferRef buffer,
+Reader::Reader(jit::JIT &engine, llvm::MemoryBufferRef buffer,
llvm::StringRef ns, std::optional filename)
- : Reader(ctx, buffer.getBuffer(), ns, filename){};
+ : Reader(engine, buffer.getBuffer(), ns, filename){};
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) {
- return *c == '\0' || currentPos > buf.size() || ((const int)*c == EOF);
+ return *c == '\0' || currentPos > buf.size() ||
+ (static_cast(*c) == EOF);
};
Location Reader::getCurrentLocation() { return currentLocation.clone(); };
@@ -208,7 +210,7 @@ bool Reader::isValidForIdentifier(char c) {
/// Reads a number,
/// \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...");
std::string number(neg ? "-" : "");
bool floatNum = false;
@@ -220,7 +222,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
LocationRange loc(getCurrentLocation());
if (isdigit(*c) == 0) {
- return errors::makeError(ctx, errors::InvalidDigitForNumber, loc);
+ return errors::make(errors::Type::InvalidDigitForNumber, loc);
}
for (;;) {
@@ -231,7 +233,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
if ((isdigit(*c) != 0) || *c == '.') {
if (*c == '.' && floatNum) {
loc = LocationRange(getCurrentLocation());
- return errors::makeError(ctx, errors::TwoFloatPoints, loc);
+ return errors::make(errors::Type::TwoFloatPoints, loc);
}
if (*c == '.') {
@@ -247,16 +249,16 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
if (((std::isalpha(*c) != 0) && !empty) || empty) {
advance();
loc.start = getCurrentLocation();
- return errors::makeError(ctx, errors::InvalidDigitForNumber, loc);
+ return errors::make(errors::Type::InvalidDigitForNumber, loc);
}
loc.end = getCurrentLocation();
- return exprs::make(loc, number, neg, floatNum);
+ return ast::make(loc, number, neg, floatNum);
};
/// Reads a symbol. If the symbol looks like a number
/// If reads it as number
-exprs::MaybeNode Reader::readSymbol() {
+ast::MaybeNode Reader::readSymbol() {
READER_LOG("Reading a symbol...");
LocationRange loc;
const auto *c = nextChar();
@@ -271,7 +273,7 @@ exprs::MaybeNode Reader::readSymbol() {
msg = "An extra ')' is detected.";
}
- return errors::makeError(ctx, errors::InvalidCharacterForSymbol, loc, msg);
+ return errors::make(errors::Type::InvalidCharacterForSymbol, loc, msg);
}
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
loc.end = getCurrentLocation();
- return exprs::makeSuccessfulNode(loc, sym, this->ns);
+ return ast::makeSuccessfulNode(loc, sym, this->ns);
};
/// Reads a list recursively
-exprs::MaybeNode Reader::readList() {
+ast::MaybeNode Reader::readList() {
READER_LOG("Reading a list...");
const auto *c = nextChar();
advance();
- auto list = exprs::makeAndCast(getCurrentLocation());
+ auto list = ast::makeAndCast(getCurrentLocation());
// TODO: Replace the assert with an actual check.
assert(*c == '(');
@@ -331,8 +333,7 @@ exprs::MaybeNode Reader::readList() {
advance(true);
advance();
list->location.end = getCurrentLocation();
- return errors::makeError(ctx, errors::EOFWhileScaningAList,
- list->location);
+ return errors::make(errors::Type::EOFWhileScaningAList, list->location);
}
switch (*c) {
@@ -359,13 +360,13 @@ exprs::MaybeNode Reader::readList() {
};
/// Reads an expression by dispatching to the proper reader function.
-exprs::MaybeNode Reader::readExpr() {
+ast::MaybeNode Reader::readExpr() {
const auto *c = nextChar(true);
READER_LOG("Read char at `readExpr`: " << *c);
if (isEndOfBuffer(c)) {
- return exprs::EmptyNode;
+ return ast::EmptyNode;
}
switch (*c) {
@@ -383,7 +384,7 @@ exprs::MaybeNode Reader::readExpr() {
/// Reads all the expressions in the reader's buffer as an AST.
/// Each expression type (from the reader perspective) has a
/// reader function.
-exprs::MaybeAst Reader::read() {
+ast::MaybeAst Reader::read() {
for (size_t current_pos = 0; current_pos < buf.size();) {
const auto *c = nextChar(true);
@@ -411,21 +412,21 @@ exprs::MaybeAst Reader::read() {
return std::move(this->ast);
};
-exprs::MaybeAst read(SereneContext &ctx, const llvm::StringRef input,
- llvm::StringRef ns,
- std::optional filename) {
- reader::Reader r(ctx, input, ns, filename);
+ast::MaybeAst read(jit::JIT &engine, const llvm::StringRef input,
+ llvm::StringRef ns,
+ std::optional filename) {
+ Reader r(engine, input, ns, filename);
auto ast = r.read();
return ast;
}
-exprs::MaybeAst read(SereneContext &ctx, const llvm::MemoryBufferRef input,
- llvm::StringRef ns,
- std::optional filename) {
- reader::Reader r(ctx, input, ns, filename);
+ast::MaybeAst read(jit::JIT &engine, const llvm::MemoryBufferRef input,
+ llvm::StringRef ns,
+ std::optional filename) {
+ Reader r(engine, input, ns, filename);
auto ast = r.read();
return ast;
}
-} // namespace reader
+
} // namespace serene
diff --git a/serene/src/reader.h b/serene/src/reader.h
index 1d837f5..ce1e1c0 100644
--- a/serene/src/reader.h
+++ b/serene/src/reader.h
@@ -43,10 +43,19 @@
#include
#include
+#define READER_LOG(...) \
+ DEBUG_WITH_TYPE("READER", llvm::dbgs() \
+ << "[READER]: " << __VA_ARGS__ << "\n");
+
namespace serene {
+namespace jit {
+class JIT;
+} // namespace jit
+
/// Base reader class which reads from a string directly.
class Reader {
private:
+ jit::JIT &engine;
llvm::StringRef ns;
std::optional filename;
@@ -77,36 +86,36 @@ private:
static bool isValidForIdentifier(char c);
// The property to store the ast tree
- Ast ast;
+ ast::Ast ast;
- MaybeNode readSymbol();
- MaybeNode readNumber(bool);
- MaybeNode readList();
- MaybeNode readExpr();
+ ast::MaybeNode readSymbol();
+ ast::MaybeNode readNumber(bool);
+ ast::MaybeNode readList();
+ ast::MaybeNode readExpr();
bool isEndOfBuffer(const char *);
public:
- Reader(llvm::StringRef buf, llvm::StringRef ns,
+ Reader(jit::JIT &engine, llvm::StringRef buf, llvm::StringRef ns,
std::optional filename);
- Reader(llvm::MemoryBufferRef buf, llvm::StringRef ns,
+ Reader(jit::JIT &engine, llvm::MemoryBufferRef buf, llvm::StringRef ns,
std::optional filename);
// void setInput(const llvm::StringRef string);
/// Parses the the input and creates a possible AST out of it or errors
/// otherwise.
- MaybeAst read();
+ ast::MaybeAst read();
~Reader();
};
/// Parses the given `input` string and returns a `Result`
/// which may contains an AST or an `llvm::Error`
-MaybeAst read(llvm::StringRef input, llvm::StringRef ns,
- std::optional filename);
-MaybeAst read(llvm::MemoryBufferRef input, llvm::StringRef ns,
- std::optional filename);
+ast::MaybeAst read(llvm::StringRef input, llvm::StringRef ns,
+ std::optional filename);
+ast::MaybeAst read(llvm::MemoryBufferRef input, llvm::StringRef ns,
+ std::optional filename);
} // namespace serene
#endif
diff --git a/serene/src/source_mgr.cpp b/serene/src/source_mgr.cpp
index 5f5ac93..89ede19 100644
--- a/serene/src/source_mgr.cpp
+++ b/serene/src/source_mgr.cpp
@@ -16,12 +16,13 @@
* along with this program. If not, see .
*/
-#include "serene/source_mgr.h"
+#include "source_mgr.h"
-#include "serene/namespace.h"
-#include "serene/reader/location.h"
-#include "serene/reader/reader.h"
-#include "serene/utils.h"
+#include "errors.h"
+#include "jit/jit.h"
+#include "location.h"
+#include "reader.h"
+#include "utils.h"
#include
@@ -75,8 +76,8 @@ SourceMgr::MemBufPtr SourceMgr::findFileInLoadPath(const std::string &name,
return nullptr;
};
-MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
- reader::LocationRange importLoc) {
+MaybeNS SourceMgr::readNamespace(jit::JIT &engine, std::string name,
+ LocationRange importLoc) {
std::string importedFile;
SMGR_LOG("Attempt to load namespace: " + name);
@@ -84,7 +85,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
if (newBufOrErr == nullptr) {
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);
@@ -93,7 +94,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
if (bufferId == 0) {
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
@@ -101,8 +102,8 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
const auto *buf = getMemoryBuffer(bufferId);
// Read the content of the buffer by passing it the reader
- auto maybeAst = reader::read(ctx, buf->getBuffer(), name,
- std::optional(llvm::StringRef(importedFile)));
+ auto maybeAst = read(jit, buf->getBuffer(), name,
+ std::optional(llvm::StringRef(importedFile)));
if (!maybeAst) {
SMGR_LOG("Couldn't Read namespace: " + name);
@@ -111,7 +112,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
// Create the NS and set the AST
auto ns =
- ctx.makeNamespace(name, std::optional(llvm::StringRef(importedFile)));
+ engine.makeNamespace(name, std::optional(llvm::StringRef(importedFile)));
if (auto errs = ns->addTree(*maybeAst)) {
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 f,
- reader::LocationRange includeLoc) {
+ LocationRange includeLoc) {
SrcBuffer nb;
nb.buffer = std::move(f);
nb.importLoc = includeLoc;
diff --git a/serene/src/source_mgr.h b/serene/src/source_mgr.h
index d5a681a..da901f9 100644
--- a/serene/src/source_mgr.h
+++ b/serene/src/source_mgr.h
@@ -20,6 +20,7 @@
#define SERENE_SOURCE_MGR_H
#include "location.h"
+#include "namespace.h"
#include
#include
@@ -38,7 +39,9 @@
<< "[SMGR]: " << __VA_ARGS__ << "\n");
namespace serene {
-class SereneContext;
+namespace jit {
+class JIT;
+} // namespace jit
/// This class is quite similar to the `llvm::SourceMgr` in functionality. We
/// 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
/// imported.
- MaybeNS readNamespace(SereneContext &ctx, std::string name,
+ MaybeNS readNamespace(jit::JIT &engine, std::string name,
LocationRange importLoc);
};