From 97c1b3e7c1a9b1901ee43fb4412689e59bfd0f0c Mon Sep 17 00:00:00 2001 From: Sameer Rahmani Date: Sun, 13 Aug 2023 20:12:07 +0100 Subject: [PATCH] move ast related files to its directory --- serene/include/serene/config.h.in | 1 + serene/src/CMakeLists.txt | 6 +-- serene/src/_errors.h | 4 +- serene/src/{ => ast}/ast.cpp | 50 +++++++++++++++++----- serene/src/{ => ast}/ast.h | 71 +++++++++++++++++++++++++++---- serene/src/errors.cpp | 9 ++++ serene/src/errors.h | 21 ++++----- serene/src/location.h | 8 ++++ serene/src/namespace.h | 2 +- serene/src/reader.cpp | 25 ++++++----- serene/src/reader.h | 13 +++--- serene/src/source_mgr.cpp | 14 +++--- serene/src/source_mgr.h | 5 +-- 13 files changed, 161 insertions(+), 68 deletions(-) rename serene/src/{ => ast}/ast.cpp (78%) rename serene/src/{ => ast}/ast.h (78%) 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