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,
TYPE,
FN,
NS,
NUMBER,
INT,
CSTRING,

View File

@ -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
)

View File

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

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ast.h"
#include "ast/ast.h"
#include <llvm/Support/FormatVariadic.h>
@ -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("<Number {0}{1}>", std::get<double>(value));
}
return llvm::formatv("<Number {0}{1}>", std::get<long>(value));
return llvm::formatv("<Number {0}{1}>", 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<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

View File

@ -16,9 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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<long, double> 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<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
/// to the constructor of type `T`. This is the **official way** to create
/// a new `Expression`. Here is an example:

View File

@ -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<Error>(t, loc, msg);
}
llvm::Error make(Type t, const LocationRange &loc) {
return llvm::make_error<Error>(t, loc);
}
} // namespace serene::errors

View File

@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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<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<Error>(t, loc);
}
llvm::Error make(Type t, const LocationRange &loc);
}; // namespace serene::errors
#endif

View File

@ -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 *);

View File

@ -37,7 +37,7 @@
#ifndef NAMESPACE_H
#define NAMESPACE_H
#include "ast.h"
#include "ast/ast.h"
#include "environment.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)
: 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<llvm::StringRef> filename)
: Reader(engine, buffer.getBuffer(), ns, filename){};
Reader::Reader(llvm::MemoryBufferRef buffer, llvm::StringRef ns,
std::optional<llvm::StringRef> 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<ast::List>(getCurrentLocation());
auto list = ast::makeAndCast<ast::List>(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<llvm::StringRef> 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<llvm::StringRef> filename) {
Reader r(engine, input, ns, filename);
Reader r(input, ns, filename);
auto ast = r.read();
return ast;

View File

@ -37,7 +37,7 @@
#ifndef READER_H
#define READER_H
#include "ast.h"
#include "ast/ast.h"
#include "location.h"
#include <llvm/ADT/StringRef.h>
@ -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<llvm::StringRef> 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<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);
// void setInput(const llvm::StringRef string);
@ -112,10 +111,10 @@ public:
/// Parses the given `input` string and returns a `Result<ast>`
/// 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);
ast::MaybeAst read(jit::JIT &engine, llvm::MemoryBufferRef input,
llvm::StringRef ns, std::optional<llvm::StringRef> filename);
} // namespace serene
#endif

View File

@ -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<ast::Namespace>(
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;
}

View File

@ -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 <llvm/ADT/SmallVector.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
/// imported.
MaybeNS readNamespace(jit::JIT &engine, std::string name,
LocationRange importLoc);
ast::MaybeNS readNamespace(std::string name, const LocationRange &importLoc);
};
}; // namespace serene