move ast related files to its directory
ci/woodpecker/push/build Pipeline was successful Details
ci/woodpecker/push/docs Pipeline was successful Details

This commit is contained in:
Sameer Rahmani 2023-08-13 20:12:07 +01:00
parent 6cfe47b6d6
commit 97c1b3e7c1
Signed by: lxsameer
GPG Key ID: B0A4AF28AB9FD90B
13 changed files with 161 additions and 68 deletions

View File

@ -33,6 +33,7 @@ typedef enum {
SYMBOL, SYMBOL,
TYPE, TYPE,
FN, FN,
NS,
NUMBER, NUMBER,
INT, INT,
CSTRING, CSTRING,

View File

@ -19,11 +19,9 @@ target_sources(serene PRIVATE
commands/commands.cpp commands/commands.cpp
jit/jit.cpp jit/jit.cpp
ast/ast.cpp
reader.cpp reader.cpp
source_mgr.cpp source_mgr.cpp
errors.cpp errors.cpp
ast.cpp
namespace.cpp
) )

View File

@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _ERRORS_H #ifndef SERENE__ERRORS_H
#define _ERRORS_H #define SERENE__ERRORS_H
#include <string> #include <string>

View File

@ -16,7 +16,7 @@
* 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 "ast.h" #include "ast/ast.h"
#include <llvm/Support/FormatVariadic.h> #include <llvm/Support/FormatVariadic.h>
@ -59,21 +59,16 @@ bool Symbol::classof(const Expression *e) {
// ============================================================================ // ============================================================================
// Number // Number
// ============================================================================ // ============================================================================
Number::Number(const LocationRange &loc, const long &num) Number::Number(const LocationRange &loc, const llvm::StringRef &n, bool neg,
: Expression(loc), value(num), isNeg(num < 0), isFloat(false){}; bool fl)
: Expression(loc), value(n), isNeg(neg), isFloat(fl){};
Number::Number(const LocationRange &loc, const double &num)
: Expression(loc), value(num), isNeg(num < 0), isFloat(true){};
Number::Number(Number &n) : Expression(n.location) { this->value = n.value; }; Number::Number(Number &n) : Expression(n.location) { this->value = n.value; };
TypeID Number::getType() const { return TypeID::NUMBER; }; TypeID Number::getType() const { return TypeID::NUMBER; };
std::string Number::toString() const { std::string Number::toString() const {
if (isFloat) { return llvm::formatv("<Number {0}{1}>", isNeg ? "-" : "", value);
return llvm::formatv("<Number {0}{1}>", std::get<double>(value));
}
return llvm::formatv("<Number {0}{1}>", std::get<long>(value));
} }
bool Number::classof(const Expression *e) { bool Number::classof(const Expression *e) {
@ -83,11 +78,18 @@ bool Number::classof(const Expression *e) {
// ============================================================================ // ============================================================================
// List // List
// ============================================================================ // ============================================================================
List::List(const LocationRange &loc) : Expression(loc){};
List::List(const LocationRange &loc, Ast &v) : Expression(loc) { List::List(const LocationRange &loc, Ast &v) : Expression(loc) {
this->elements.swap(v); this->elements.swap(v);
v.clear(); 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; }; TypeID List::getType() const { return TypeID::LIST; };
std::string List::toString() const { std::string List::toString() const {
@ -165,4 +167,32 @@ bool Error::classof(const Expression *e) {
return e->getType() == TypeID::KEYWORD; 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<llvm::StringRef> filename)
: Expression(loc), name(name), filename(filename) {
createEnv(nullptr);
};
Namespace::SemanticEnv &Namespace::createEnv(SemanticEnv *parent) {
auto env = std::make_unique<SemanticEnv>(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("<NS {0}>", name);
}
bool Namespace::classof(const Expression *e) {
return e->getType() == TypeID::NS;
};
} // namespace serene::ast } // namespace serene::ast

View File

@ -16,9 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef AST_H #ifndef AST_AST_H
#define AST_H #define AST_AST_H
#include "environment.h"
#include "location.h" #include "location.h"
#include "serene/config.h" #include "serene/config.h"
@ -44,7 +45,6 @@ constexpr static auto EmptyNode = nullptr;
// common interface for the expressions to implement. // common interface for the expressions to implement.
// ============================================================================ // ============================================================================
struct Expression { struct Expression {
/// The location range provide information regarding to where in the input /// The location range provide information regarding to where in the input
/// string the current expression is used. /// string the current expression is used.
LocationRange location; LocationRange location;
@ -101,15 +101,13 @@ struct Symbol : public Expression {
// ============================================================================ // ============================================================================
struct Number : public Expression { struct Number : public Expression {
// TODO: [ast] Split the number type into their own types // TODO: [ast] Split the number type into their own types
std::variant<long, double> value; std::string value;
// /TODO // /TODO
bool isNeg; bool isNeg;
bool isFloat; bool isFloat;
Number(const LocationRange &loc, const long &num); Number(const LocationRange &loc, const llvm::StringRef &n, bool neg, bool fl);
Number(const LocationRange &loc, const unsigned long &num);
Number(const LocationRange &loc, const double &num);
Number(Number &n); Number(Number &n);
TypeID getType() const override; TypeID getType() const override;
@ -126,9 +124,10 @@ struct Number : public Expression {
struct List : public Expression { struct List : public Expression {
Ast elements; Ast elements;
explicit List(const LocationRange &loc);
List(const LocationRange &loc, Ast &v); List(const LocationRange &loc, Ast &v);
List(const List &l) = delete; List(const List &l) = delete;
List(List &&l) noexcept = default; List(List &&l) noexcept;
TypeID getType() const override; TypeID getType() const override;
std::string toString() const override; std::string toString() const override;
@ -197,6 +196,60 @@ struct Error : public Expression {
static bool classof(const Expression *e); static bool classof(const Expression *e);
}; };
// ============================================================================
// Namespace
// ============================================================================
struct Namespace : public Expression {
using SemanticEnv = Environment<Node>;
using SemanticEnvPtr = std::unique_ptr<SemanticEnv>;
using SemanticEnvironments = std::vector<SemanticEnvPtr>;
std::string name;
std::optional<std::string> filename;
Ast tree;
SemanticEnvironments environments;
Namespace(const LocationRange &loc, llvm::StringRef name);
Namespace(const LocationRange &loc, llvm::StringRef name,
std::optional<llvm::StringRef> 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<std::unique_ptr<Namespace>>;
/// Create a new `node` of type `T` and forwards any given parameter /// 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 /// to the constructor of type `T`. This is the **official way** to create
/// a new `Expression`. Here is an example: /// a new `Expression`. Here is an example:

View File

@ -32,4 +32,13 @@ std::string getMessage(const llvm::Error &e) {
os << e; os << e;
return os.str(); return os.str();
}; };
llvm::Error make(Type t, const LocationRange &loc, llvm::StringRef msg) {
return llvm::make_error<Error>(t, loc, msg);
}
llvm::Error make(Type t, const LocationRange &loc) {
return llvm::make_error<Error>(t, loc);
}
} // namespace serene::errors } // namespace serene::errors

View File

@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef ERRORS_H #ifndef SERENE_ERRORS_H
#define ERRORS_H #define SERENE_ERRORS_H
#include "_errors.h" #include "_errors.h"
#include "location.h" #include "location.h"
@ -35,7 +35,7 @@ public:
static char ID; static char ID;
Type type; Type type;
LocationRange location; const LocationRange location;
std::string msg; std::string msg;
void log(llvm::raw_ostream &os) const override { os << 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); 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()){}; : 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) { llvm::Error make(Type t, const LocationRange &loc, llvm::StringRef msg);
return llvm::make_error<Error>(t, loc, msg);
}
llvm::Error make(Type t, LocationRange &loc) { llvm::Error make(Type t, const LocationRange &loc);
return llvm::make_error<Error>(t, loc);
}
}; // namespace serene::errors }; // namespace serene::errors
#endif #endif

View File

@ -62,6 +62,8 @@ struct Location {
static Location UnknownLocation(llvm::StringRef ns) { static Location UnknownLocation(llvm::StringRef ns) {
return Location(ns, std::nullopt, nullptr, 0, 0, false); return Location(ns, std::nullopt, nullptr, 0, 0, false);
} }
~Location() = default;
}; };
class LocationRange { class LocationRange {
@ -74,11 +76,17 @@ public:
LocationRange(Location _start, Location _end) : start(_start), end(_end){}; LocationRange(Location _start, Location _end) : start(_start), end(_end){};
// LocationRange(const LocationRange &); // 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; }; bool isKnownLocation() const { return start.knownLocation; };
static LocationRange UnknownLocation(llvm::StringRef ns) { static LocationRange UnknownLocation(llvm::StringRef ns) {
return LocationRange(Location::UnknownLocation(ns)); return LocationRange(Location::UnknownLocation(ns));
} }
~LocationRange() = default;
}; };
void incLocation(Location &, const char *); void incLocation(Location &, const char *);

View File

@ -37,7 +37,7 @@
#ifndef NAMESPACE_H #ifndef NAMESPACE_H
#define NAMESPACE_H #define NAMESPACE_H
#include "ast.h" #include "ast/ast.h"
#include "environment.h" #include "environment.h"
#include "utils.h" #include "utils.h"

View File

@ -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<llvm::StringRef> filename) std::optional<llvm::StringRef> filename)
: engine(engine), ns(ns), filename(filename), buf(buffer), : ns(ns), filename(filename), buf(buffer),
currentLocation(Location(ns, filename)) { currentLocation(Location(ns, filename)) {
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;
@ -111,9 +111,9 @@ Reader::Reader(jit::JIT &engine, llvm::StringRef buffer, llvm::StringRef ns,
currentLocation.col = 1; currentLocation.col = 1;
}; };
Reader::Reader(jit::JIT &engine, llvm::MemoryBufferRef buffer, Reader::Reader(llvm::MemoryBufferRef buffer, llvm::StringRef ns,
llvm::StringRef ns, std::optional<llvm::StringRef> filename) std::optional<llvm::StringRef> filename)
: Reader(engine, buffer.getBuffer(), ns, filename){}; : Reader(buffer.getBuffer(), ns, filename){};
Reader::~Reader() { READER_LOG("Destroying the reader"); } Reader::~Reader() { READER_LOG("Destroying the reader"); }
@ -317,9 +317,10 @@ ast::MaybeNode Reader::readList() {
READER_LOG("Reading a list..."); READER_LOG("Reading a list...");
const auto *c = nextChar(); const auto *c = nextChar();
LocationRange loc(getCurrentLocation());
advance(); advance();
auto list = ast::makeAndCast<ast::List>(getCurrentLocation()); auto list = ast::makeAndCast<ast::List>(loc);
// TODO: Replace the assert with an actual check. // TODO: Replace the assert with an actual check.
assert(*c == '('); assert(*c == '(');
@ -412,18 +413,16 @@ ast::MaybeAst Reader::read() {
return std::move(this->ast); return std::move(this->ast);
}; };
ast::MaybeAst read(jit::JIT &engine, const llvm::StringRef input, ast::MaybeAst read(const llvm::StringRef input, llvm::StringRef ns,
llvm::StringRef ns,
std::optional<llvm::StringRef> filename) { std::optional<llvm::StringRef> filename) {
Reader r(engine, input, ns, filename); Reader r(input, ns, filename);
auto ast = r.read(); auto ast = r.read();
return ast; return ast;
} }
ast::MaybeAst read(jit::JIT &engine, const llvm::MemoryBufferRef input, ast::MaybeAst read(const llvm::MemoryBufferRef input, llvm::StringRef ns,
llvm::StringRef ns,
std::optional<llvm::StringRef> filename) { std::optional<llvm::StringRef> filename) {
Reader r(engine, input, ns, filename); Reader r(input, ns, filename);
auto ast = r.read(); auto ast = r.read();
return ast; return ast;

View File

@ -37,7 +37,7 @@
#ifndef READER_H #ifndef READER_H
#define READER_H #define READER_H
#include "ast.h" #include "ast/ast.h"
#include "location.h" #include "location.h"
#include <llvm/ADT/StringRef.h> #include <llvm/ADT/StringRef.h>
@ -55,7 +55,6 @@ class 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;
@ -96,9 +95,9 @@ private:
bool isEndOfBuffer(const char *); bool isEndOfBuffer(const char *);
public: public:
Reader(jit::JIT &engine, llvm::StringRef buf, llvm::StringRef ns, Reader(llvm::StringRef buf, llvm::StringRef ns,
std::optional<llvm::StringRef> filename); std::optional<llvm::StringRef> filename);
Reader(jit::JIT &engine, llvm::MemoryBufferRef buf, llvm::StringRef ns, Reader(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);
@ -112,10 +111,10 @@ public:
/// 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`
ast::MaybeAst read(jit::JIT &engine, llvm::StringRef input, llvm::StringRef ns, ast::MaybeAst read(llvm::StringRef input, llvm::StringRef ns,
std::optional<llvm::StringRef> filename);
ast::MaybeAst read(llvm::MemoryBufferRef input, llvm::StringRef ns,
std::optional<llvm::StringRef> filename); std::optional<llvm::StringRef> filename);
ast::MaybeAst read(jit::JIT &engine, llvm::MemoryBufferRef input,
llvm::StringRef ns, std::optional<llvm::StringRef> filename);
} // namespace serene } // namespace serene
#endif #endif

View File

@ -76,8 +76,8 @@ SourceMgr::MemBufPtr SourceMgr::findFileInLoadPath(const std::string &name,
return nullptr; return nullptr;
}; };
MaybeNS SourceMgr::readNamespace(jit::JIT &engine, std::string name, ast::MaybeNS SourceMgr::readNamespace(std::string name,
LocationRange importLoc) { const LocationRange &importLoc) {
std::string importedFile; std::string importedFile;
SMGR_LOG("Attempt to load namespace: " + name); 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); 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 = read(engine, buf->getBuffer(), name, auto maybeAst = read(buf->getBuffer(), name,
std::optional(llvm::StringRef(importedFile))); std::optional(llvm::StringRef(importedFile)));
if (!maybeAst) { if (!maybeAst) {
@ -111,11 +111,11 @@ MaybeNS SourceMgr::readNamespace(jit::JIT &engine, std::string name,
} }
// Create the NS and set the AST // Create the NS and set the AST
auto ns = auto ns = ast::makeAndCast<ast::Namespace>(
engine.makeNamespace(name, std::optional(llvm::StringRef(importedFile))); importLoc, name, std::optional(llvm::StringRef(importedFile)));
if (auto errs = ns->addTree(*maybeAst)) { if (auto errs = ns->ExpandTree(*maybeAst)) {
SMGR_LOG("Couldn't set the AST for namespace: " + name); SMGR_LOG("Couldn't set thre AST for namespace: " + name);
return errs; return errs;
} }

View File

@ -19,8 +19,8 @@
#ifndef SERENE_SOURCE_MGR_H #ifndef SERENE_SOURCE_MGR_H
#define SERENE_SOURCE_MGR_H #define SERENE_SOURCE_MGR_H
#include "ast/ast.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>
@ -184,8 +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(jit::JIT &engine, std::string name, ast::MaybeNS readNamespace(std::string name, const LocationRange &importLoc);
LocationRange importLoc);
}; };
}; // namespace serene }; // namespace serene