diff --git a/serene/include/serene/config.h.in b/serene/include/serene/config.h.in
index 2feb0c4..cb61a59 100644
--- a/serene/include/serene/config.h.in
+++ b/serene/include/serene/config.h.in
@@ -33,6 +33,7 @@ typedef enum {
SYMBOL,
TYPE,
FN,
+ NS,
NUMBER,
INT,
CSTRING,
diff --git a/serene/src/CMakeLists.txt b/serene/src/CMakeLists.txt
index c1488da..7a73174 100644
--- a/serene/src/CMakeLists.txt
+++ b/serene/src/CMakeLists.txt
@@ -19,11 +19,9 @@ target_sources(serene PRIVATE
commands/commands.cpp
jit/jit.cpp
-
+ ast/ast.cpp
reader.cpp
+
source_mgr.cpp
errors.cpp
- ast.cpp
- namespace.cpp
-
)
diff --git a/serene/src/_errors.h b/serene/src/_errors.h
index 9f2ae74..d25a0da 100644
--- a/serene/src/_errors.h
+++ b/serene/src/_errors.h
@@ -16,8 +16,8 @@
* along with this program. If not, see .
*/
-#ifndef _ERRORS_H
-#define _ERRORS_H
+#ifndef SERENE__ERRORS_H
+#define SERENE__ERRORS_H
#include
diff --git a/serene/src/ast.cpp b/serene/src/ast/ast.cpp
similarity index 78%
rename from serene/src/ast.cpp
rename to serene/src/ast/ast.cpp
index 6019f0d..48f5a85 100644
--- a/serene/src/ast.cpp
+++ b/serene/src/ast/ast.cpp
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-#include "ast.h"
+#include "ast/ast.h"
#include
@@ -59,21 +59,16 @@ bool Symbol::classof(const Expression *e) {
// ============================================================================
// Number
// ============================================================================
-Number::Number(const LocationRange &loc, const long &num)
- : Expression(loc), value(num), isNeg(num < 0), isFloat(false){};
-
-Number::Number(const LocationRange &loc, const double &num)
- : Expression(loc), value(num), isNeg(num < 0), isFloat(true){};
+Number::Number(const LocationRange &loc, const llvm::StringRef &n, bool neg,
+ bool fl)
+ : Expression(loc), value(n), isNeg(neg), isFloat(fl){};
Number::Number(Number &n) : Expression(n.location) { this->value = n.value; };
TypeID Number::getType() const { return TypeID::NUMBER; };
std::string Number::toString() const {
- if (isFloat) {
- return llvm::formatv("", std::get(value));
- }
- return llvm::formatv("", std::get(value));
+ return llvm::formatv("", isNeg ? "-" : "", value);
}
bool Number::classof(const Expression *e) {
@@ -83,11 +78,18 @@ bool Number::classof(const Expression *e) {
// ============================================================================
// List
// ============================================================================
+List::List(const LocationRange &loc) : Expression(loc){};
+
List::List(const LocationRange &loc, Ast &v) : Expression(loc) {
this->elements.swap(v);
v.clear();
};
+List::List(List &&l) noexcept : Expression(l.location) {
+ this->elements.swap(l.elements);
+ l.elements.clear();
+};
+
TypeID List::getType() const { return TypeID::LIST; };
std::string List::toString() const {
@@ -165,4 +167,32 @@ bool Error::classof(const Expression *e) {
return e->getType() == TypeID::KEYWORD;
};
+// ============================================================================
+// Namespace
+// ============================================================================
+Namespace::Namespace(const LocationRange &loc, llvm::StringRef name)
+ : Namespace(loc, name, std::nullopt){};
+Namespace::Namespace(const LocationRange &loc, llvm::StringRef name,
+ std::optional filename)
+ : Expression(loc), name(name), filename(filename) {
+ createEnv(nullptr);
+};
+
+Namespace::SemanticEnv &Namespace::createEnv(SemanticEnv *parent) {
+ auto env = std::make_unique(parent);
+ environments.push_back(std::move(env));
+
+ return *environments.back();
+};
+
+TypeID Namespace::getType() const { return TypeID::NS; };
+
+std::string Namespace::toString() const {
+ return llvm::formatv("", name);
+}
+
+bool Namespace::classof(const Expression *e) {
+ return e->getType() == TypeID::NS;
+};
+
} // namespace serene::ast
diff --git a/serene/src/ast.h b/serene/src/ast/ast.h
similarity index 78%
rename from serene/src/ast.h
rename to serene/src/ast/ast.h
index 3a6f493..77364dd 100644
--- a/serene/src/ast.h
+++ b/serene/src/ast/ast.h
@@ -16,9 +16,10 @@
* along with this program. If not, see .
*/
-#ifndef AST_H
-#define AST_H
+#ifndef AST_AST_H
+#define AST_AST_H
+#include "environment.h"
#include "location.h"
#include "serene/config.h"
@@ -44,7 +45,6 @@ constexpr static auto EmptyNode = nullptr;
// common interface for the expressions to implement.
// ============================================================================
struct Expression {
-
/// The location range provide information regarding to where in the input
/// string the current expression is used.
LocationRange location;
@@ -101,15 +101,13 @@ struct Symbol : public Expression {
// ============================================================================
struct Number : public Expression {
// TODO: [ast] Split the number type into their own types
- std::variant value;
+ std::string value;
// /TODO
bool isNeg;
bool isFloat;
- Number(const LocationRange &loc, const long &num);
- Number(const LocationRange &loc, const unsigned long &num);
- Number(const LocationRange &loc, const double &num);
+ Number(const LocationRange &loc, const llvm::StringRef &n, bool neg, bool fl);
Number(Number &n);
TypeID getType() const override;
@@ -126,9 +124,10 @@ struct Number : public Expression {
struct List : public Expression {
Ast elements;
+ explicit List(const LocationRange &loc);
List(const LocationRange &loc, Ast &v);
- List(const List &l) = delete;
- List(List &&l) noexcept = default;
+ List(const List &l) = delete;
+ List(List &&l) noexcept;
TypeID getType() const override;
std::string toString() const override;
@@ -197,6 +196,60 @@ struct Error : public Expression {
static bool classof(const Expression *e);
};
+// ============================================================================
+// Namespace
+// ============================================================================
+struct Namespace : public Expression {
+ using SemanticEnv = Environment;
+ using SemanticEnvPtr = std::unique_ptr;
+ using SemanticEnvironments = std::vector;
+
+ std::string name;
+ std::optional filename;
+
+ Ast tree;
+
+ SemanticEnvironments environments;
+
+ Namespace(const LocationRange &loc, llvm::StringRef name);
+ Namespace(const LocationRange &loc, llvm::StringRef name,
+ std::optional filename);
+ Namespace(Namespace &s) = delete;
+
+ /// Create a new environment with the give \p parent as the parent,
+ /// push the environment to the internal environment storage and
+ /// return a reference to it. The namespace itself is the owner of
+ /// environments.
+ SemanticEnv &createEnv(SemanticEnv *parent);
+
+ /// Return a referenece to the top level (root) environment of ns.
+ SemanticEnv &getRootEnv();
+
+ /// Define a new binding in the root environment with the given \p name
+ /// and the given \p node. Defining a new binding with a name that
+ /// already exists in legal and will overwrite the previous binding and
+ /// the given name will point to a new value from now on.
+ mlir::LogicalResult define(std::string &name, Node &node);
+
+ /// Add the given \p ast to the namespace and return any possible error.
+ /// The given \p ast will be added to a vector of ASTs by expanding
+ /// the tree vector to contain \p ast.
+ ///
+ /// This function runs the semantic analyzer on the \p ast as well.
+ llvm::Error ExpandTree(Ast &ast);
+
+ Ast &getTree();
+
+ TypeID getType() const override;
+ std::string toString() const override;
+
+ ~Namespace() = default;
+
+ static bool classof(const Expression *e);
+};
+
+using MaybeNS = llvm::Expected>;
+
/// Create a new `node` of type `T` and forwards any given parameter
/// to the constructor of type `T`. This is the **official way** to create
/// a new `Expression`. Here is an example:
diff --git a/serene/src/errors.cpp b/serene/src/errors.cpp
index 3995ca6..7d37069 100644
--- a/serene/src/errors.cpp
+++ b/serene/src/errors.cpp
@@ -32,4 +32,13 @@ std::string getMessage(const llvm::Error &e) {
os << e;
return os.str();
};
+
+llvm::Error make(Type t, const LocationRange &loc, llvm::StringRef msg) {
+ return llvm::make_error(t, loc, msg);
+}
+
+llvm::Error make(Type t, const LocationRange &loc) {
+ return llvm::make_error(t, loc);
+}
+
} // namespace serene::errors
diff --git a/serene/src/errors.h b/serene/src/errors.h
index 0dea5b1..3e2faf5 100644
--- a/serene/src/errors.h
+++ b/serene/src/errors.h
@@ -16,8 +16,8 @@
* along with this program. If not, see .
*/
-#ifndef ERRORS_H
-#define ERRORS_H
+#ifndef SERENE_ERRORS_H
+#define SERENE_ERRORS_H
#include "_errors.h"
#include "location.h"
@@ -35,7 +35,7 @@ public:
static char ID;
Type type;
- LocationRange location;
+ const LocationRange location;
std::string msg;
void log(llvm::raw_ostream &os) const override { os << msg; }
@@ -46,21 +46,18 @@ public:
return std::make_error_code(std::errc::io_error);
}
- Error(Type errtype, LocationRange &loc) : type(errtype), location(loc){};
+ Error(Type errtype, const LocationRange &loc)
+ : type(errtype), location(loc){};
- Error(Type errtype, LocationRange &loc, llvm::StringRef msg)
+ Error(Type errtype, const LocationRange &loc, llvm::StringRef msg)
: type(errtype), location(loc), msg(msg.str()){};
- LocationRange &where() { return location; };
+ const 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, const LocationRange &loc, llvm::StringRef msg);
-llvm::Error make(Type t, LocationRange &loc) {
- return llvm::make_error(t, loc);
-}
+llvm::Error make(Type t, const LocationRange &loc);
}; // namespace serene::errors
#endif
diff --git a/serene/src/location.h b/serene/src/location.h
index 2f596fb..9949e5f 100644
--- a/serene/src/location.h
+++ b/serene/src/location.h
@@ -62,6 +62,8 @@ struct Location {
static Location UnknownLocation(llvm::StringRef ns) {
return Location(ns, std::nullopt, nullptr, 0, 0, false);
}
+
+ ~Location() = default;
};
class LocationRange {
@@ -74,11 +76,17 @@ public:
LocationRange(Location _start, Location _end) : start(_start), end(_end){};
// LocationRange(const LocationRange &);
+ LocationRange(LocationRange &lr) : start(lr.start), end(lr.end){};
+
+ LocationRange(const LocationRange &lr) : start(lr.start), end(lr.end){};
+
bool isKnownLocation() const { return start.knownLocation; };
static LocationRange UnknownLocation(llvm::StringRef ns) {
return LocationRange(Location::UnknownLocation(ns));
}
+
+ ~LocationRange() = default;
};
void incLocation(Location &, const char *);
diff --git a/serene/src/namespace.h b/serene/src/namespace.h
index 23411ec..da2cf96 100644
--- a/serene/src/namespace.h
+++ b/serene/src/namespace.h
@@ -37,7 +37,7 @@
#ifndef NAMESPACE_H
#define NAMESPACE_H
-#include "ast.h"
+#include "ast/ast.h"
#include "environment.h"
#include "utils.h"
diff --git a/serene/src/reader.cpp b/serene/src/reader.cpp
index e425875..56bfed6 100644
--- a/serene/src/reader.cpp
+++ b/serene/src/reader.cpp
@@ -99,11 +99,11 @@ void decLocation(Location &loc, const char *c) {
}
}
-Reader::Reader(jit::JIT &engine, llvm::StringRef buffer, llvm::StringRef ns,
+Reader::Reader(llvm::StringRef buffer, llvm::StringRef ns,
std::optional filename)
- : engine(engine), ns(ns), filename(filename), buf(buffer),
+ : ns(ns), filename(filename), buf(buffer),
currentLocation(Location(ns, filename)) {
- UNUSED(this->engine);
+
READER_LOG("Setting the first char of the buffer");
currentChar = buf.begin() - 1;
currentPos = 1;
@@ -111,9 +111,9 @@ Reader::Reader(jit::JIT &engine, llvm::StringRef buffer, llvm::StringRef ns,
currentLocation.col = 1;
};
-Reader::Reader(jit::JIT &engine, llvm::MemoryBufferRef buffer,
- llvm::StringRef ns, std::optional filename)
- : Reader(engine, buffer.getBuffer(), ns, filename){};
+Reader::Reader(llvm::MemoryBufferRef buffer, llvm::StringRef ns,
+ std::optional filename)
+ : Reader(buffer.getBuffer(), ns, filename){};
Reader::~Reader() { READER_LOG("Destroying the reader"); }
@@ -317,9 +317,10 @@ ast::MaybeNode Reader::readList() {
READER_LOG("Reading a list...");
const auto *c = nextChar();
+ LocationRange loc(getCurrentLocation());
advance();
- auto list = ast::makeAndCast(getCurrentLocation());
+ auto list = ast::makeAndCast(loc);
// TODO: Replace the assert with an actual check.
assert(*c == '(');
@@ -412,18 +413,16 @@ ast::MaybeAst Reader::read() {
return std::move(this->ast);
};
-ast::MaybeAst read(jit::JIT &engine, const llvm::StringRef input,
- llvm::StringRef ns,
+ast::MaybeAst read(const llvm::StringRef input, llvm::StringRef ns,
std::optional filename) {
- Reader r(engine, input, ns, filename);
+ Reader r(input, ns, filename);
auto ast = r.read();
return ast;
}
-ast::MaybeAst read(jit::JIT &engine, const llvm::MemoryBufferRef input,
- llvm::StringRef ns,
+ast::MaybeAst read(const llvm::MemoryBufferRef input, llvm::StringRef ns,
std::optional filename) {
- Reader r(engine, input, ns, filename);
+ Reader r(input, ns, filename);
auto ast = r.read();
return ast;
diff --git a/serene/src/reader.h b/serene/src/reader.h
index d0e3de7..975e9b5 100644
--- a/serene/src/reader.h
+++ b/serene/src/reader.h
@@ -37,7 +37,7 @@
#ifndef READER_H
#define READER_H
-#include "ast.h"
+#include "ast/ast.h"
#include "location.h"
#include
@@ -55,7 +55,6 @@ class JIT;
/// Base reader class which reads from a string directly.
class Reader {
private:
- jit::JIT &engine;
llvm::StringRef ns;
std::optional filename;
@@ -96,9 +95,9 @@ private:
bool isEndOfBuffer(const char *);
public:
- Reader(jit::JIT &engine, llvm::StringRef buf, llvm::StringRef ns,
+ Reader(llvm::StringRef buf, llvm::StringRef ns,
std::optional filename);
- Reader(jit::JIT &engine, llvm::MemoryBufferRef buf, llvm::StringRef ns,
+ Reader(llvm::MemoryBufferRef buf, llvm::StringRef ns,
std::optional filename);
// void setInput(const llvm::StringRef string);
@@ -112,10 +111,10 @@ public:
/// Parses the given `input` string and returns a `Result`
/// which may contains an AST or an `llvm::Error`
-ast::MaybeAst read(jit::JIT &engine, llvm::StringRef input, llvm::StringRef ns,
+ast::MaybeAst read(llvm::StringRef input, llvm::StringRef ns,
+ std::optional filename);
+ast::MaybeAst read(llvm::MemoryBufferRef input, llvm::StringRef ns,
std::optional filename);
-ast::MaybeAst read(jit::JIT &engine, 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 eb09085..bd93ab1 100644
--- a/serene/src/source_mgr.cpp
+++ b/serene/src/source_mgr.cpp
@@ -76,8 +76,8 @@ SourceMgr::MemBufPtr SourceMgr::findFileInLoadPath(const std::string &name,
return nullptr;
};
-MaybeNS SourceMgr::readNamespace(jit::JIT &engine, std::string name,
- LocationRange importLoc) {
+ast::MaybeNS SourceMgr::readNamespace(std::string name,
+ const LocationRange &importLoc) {
std::string importedFile;
SMGR_LOG("Attempt to load namespace: " + name);
@@ -102,7 +102,7 @@ MaybeNS SourceMgr::readNamespace(jit::JIT &engine, std::string name,
const auto *buf = getMemoryBuffer(bufferId);
// Read the content of the buffer by passing it the reader
- auto maybeAst = read(engine, buf->getBuffer(), name,
+ auto maybeAst = read(buf->getBuffer(), name,
std::optional(llvm::StringRef(importedFile)));
if (!maybeAst) {
@@ -111,11 +111,11 @@ MaybeNS SourceMgr::readNamespace(jit::JIT &engine, std::string name,
}
// Create the NS and set the AST
- auto ns =
- engine.makeNamespace(name, std::optional(llvm::StringRef(importedFile)));
+ auto ns = ast::makeAndCast(
+ importLoc, name, std::optional(llvm::StringRef(importedFile)));
- if (auto errs = ns->addTree(*maybeAst)) {
- SMGR_LOG("Couldn't set the AST for namespace: " + name);
+ if (auto errs = ns->ExpandTree(*maybeAst)) {
+ SMGR_LOG("Couldn't set thre AST for namespace: " + name);
return errs;
}
diff --git a/serene/src/source_mgr.h b/serene/src/source_mgr.h
index 8c0f5d0..f19ecda 100644
--- a/serene/src/source_mgr.h
+++ b/serene/src/source_mgr.h
@@ -19,8 +19,8 @@
#ifndef SERENE_SOURCE_MGR_H
#define SERENE_SOURCE_MGR_H
+#include "ast/ast.h"
#include "location.h"
-#include "namespace.h"
#include
#include
@@ -184,8 +184,7 @@ public:
///
/// \p importLoc is a location in the source code where the give namespace is
/// imported.
- MaybeNS readNamespace(jit::JIT &engine, std::string name,
- LocationRange importLoc);
+ ast::MaybeNS readNamespace(std::string name, const LocationRange &importLoc);
};
}; // namespace serene