Replace the shared_ptr in the node with a unique ptr
This commit is contained in:
parent
1330bad6fb
commit
3b6d165baa
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "serene/serene.h"
|
||||
#include "serene/reader/reader.h"
|
||||
#include "serene/reader/semantics.h"
|
||||
#include "serene/sir/sir.hpp"
|
||||
#include <iostream>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
|
@ -34,7 +35,7 @@ using namespace serene;
|
|||
namespace cl = llvm::cl;
|
||||
|
||||
namespace {
|
||||
enum Action { None, DumpAST, DumpIR };
|
||||
enum Action { None, DumpAST, DumpIR, DumpSemantic };
|
||||
}
|
||||
|
||||
static cl::opt<std::string> inputFile(cl::Positional,
|
||||
|
@ -42,10 +43,14 @@ static cl::opt<std::string> inputFile(cl::Positional,
|
|||
cl::init("-"),
|
||||
cl::value_desc("filename"));
|
||||
|
||||
static cl::opt<enum Action>
|
||||
emitAction("emit", cl::desc("Select what to dump."),
|
||||
cl::values(clEnumValN(DumpIR, "sir", "Output the SLIR only")),
|
||||
cl::values(clEnumValN(DumpAST, "ast", "Output the AST only")));
|
||||
static cl::opt<enum Action> emitAction(
|
||||
"emit", cl::desc("Select what to dump."),
|
||||
cl::values(clEnumValN(DumpSemantic, "ast1",
|
||||
"Output the AST after one level of analysis only")),
|
||||
cl::values(clEnumValN(DumpIR, "sir", "Output the SLIR only")),
|
||||
cl::values(clEnumValN(DumpAST, "ast", "Output the AST only"))
|
||||
|
||||
);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
cl::ParseCommandLineOptions(argc, argv, "Serene compiler \n");
|
||||
|
@ -56,16 +61,39 @@ int main(int argc, char *argv[]) {
|
|||
r->toString();
|
||||
delete r;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
case Action::DumpSemantic: {
|
||||
reader::FileReader *r = new reader::FileReader(inputFile);
|
||||
reader::Semantics analyzer;
|
||||
auto maybeAst = r->read();
|
||||
|
||||
if (!maybeAst) {
|
||||
throw std::move(maybeAst.getError());
|
||||
}
|
||||
auto &ast = maybeAst.getValue();
|
||||
auto afterAst = analyzer.analyze(ast);
|
||||
|
||||
if (afterAst) {
|
||||
// dump(afterAst.getValue());
|
||||
delete r;
|
||||
return 0;
|
||||
} else {
|
||||
throw std::move(afterAst.getError());
|
||||
}
|
||||
|
||||
delete r;
|
||||
return 0;
|
||||
};
|
||||
case Action::DumpIR: {
|
||||
reader::FileReader *r = new reader::FileReader(inputFile);
|
||||
auto ast = r->read();
|
||||
|
||||
if (!ast) {
|
||||
throw ast.takeError();
|
||||
throw std::move(ast.getError());
|
||||
}
|
||||
|
||||
serene::sir::dumpSIR(*ast);
|
||||
serene::sir::dumpSIR(ast.getValue());
|
||||
delete r;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
(def a true)
|
||||
;; (defn hello! (name)
|
||||
;; (println "Hello %s" name))
|
||||
|
|
|
@ -47,9 +47,11 @@ enum class ExprType {
|
|||
};
|
||||
class Expression;
|
||||
|
||||
using node = std::shared_ptr<Expression>;
|
||||
using node = std::unique_ptr<Expression>;
|
||||
using maybe_node = Result<node>;
|
||||
|
||||
using ast = llvm::SmallVector<node, 0>;
|
||||
using maybe_ast = Result<ast>;
|
||||
|
||||
/// The base class of the expressions which provides the common interface for
|
||||
/// the expressions to implement.
|
||||
|
@ -84,7 +86,7 @@ public:
|
|||
/// passed to the constructor of type T.
|
||||
/// \return A shared pointer to an Expression
|
||||
template <typename T, typename... Args> node make(Args &&...args) {
|
||||
return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||
};
|
||||
|
||||
/// Create a new `node` of type `T` and forwards any given parameter
|
||||
|
@ -98,10 +100,12 @@ template <typename T, typename... Args> node make(Args &&...args) {
|
|||
/// passed to the constructor of type T.
|
||||
/// \return A shared pointer to a value of type T.
|
||||
template <typename T, typename... Args>
|
||||
std::shared_ptr<T> makeAndCast(Args &&...args) {
|
||||
return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
std::unique_ptr<T> makeAndCast(Args &&...args) {
|
||||
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||
};
|
||||
|
||||
void dump(ast &);
|
||||
|
||||
} // namespace exprs
|
||||
} // namespace serene
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ public:
|
|||
List(List &&e) noexcept = default; // Move ctor
|
||||
|
||||
List(const reader::LocationRange &loc) : Expression(loc){};
|
||||
List(const reader::LocationRange &loc, node e);
|
||||
List(const reader::LocationRange &loc, llvm::ArrayRef<node> elems);
|
||||
List(const reader::LocationRange &loc, node &e);
|
||||
List(const reader::LocationRange &loc, llvm::MutableArrayRef<node> elems);
|
||||
|
||||
ExprType getType() const;
|
||||
std::string toString() const;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/* -*- C++ -*-
|
||||
* Serene programming language.
|
||||
*
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
|
||||
void setInput(const llvm::StringRef string);
|
||||
|
||||
llvm::Expected<exprs::ast> read();
|
||||
exprs::maybe_ast read();
|
||||
|
||||
// Dumps the AST data to stdout
|
||||
void toString();
|
||||
|
@ -92,7 +92,7 @@ public:
|
|||
// Dumps the AST data to stdout
|
||||
void toString();
|
||||
|
||||
llvm::Expected<exprs::ast> read();
|
||||
exprs::maybe_ast read();
|
||||
|
||||
~FileReader();
|
||||
};
|
||||
|
|
|
@ -37,7 +37,7 @@ class Semantics {
|
|||
public:
|
||||
Semantics(){};
|
||||
|
||||
exprs::maybe_node analyze(exprs::ast &);
|
||||
exprs::maybe_ast analyze(exprs::ast &);
|
||||
};
|
||||
}; // namespace serene::reader
|
||||
|
||||
|
|
|
@ -67,16 +67,22 @@ public:
|
|||
return Result(std::in_place_index_t<1>(), std::move(e));
|
||||
}
|
||||
|
||||
/// Return the value if it's successful otherwise throw an error
|
||||
T &&getValue() && { return std::move(std::get<0>(contents)); };
|
||||
|
||||
/// Return the error value if it's errorful otherwise throw an error
|
||||
E &&getError() && { return std::move(std::get<1>(contents)); };
|
||||
|
||||
// using std::get, it'll throw if contents doesn't contain what you ask for
|
||||
|
||||
/// Return the value if it's successful otherwise throw an error
|
||||
T &getValue() { return std::get<0>(contents); };
|
||||
T &getValue() & { return std::get<0>(contents); };
|
||||
|
||||
/// Return the error value if it's errorful otherwise throw an error
|
||||
E &getError() { return std::get<1>(contents); };
|
||||
E &getError() & { return std::get<1>(contents); };
|
||||
|
||||
const T &getValue() const { return std::get<0>(contents); }
|
||||
const E &getError() const { return std::get<1>(contents); }
|
||||
const T &getValue() const & { return std::get<0>(contents); }
|
||||
const E &getError() const & { return std::get<1>(contents); }
|
||||
|
||||
/// Return the a boolean value indicating whether the value is succesful
|
||||
/// or errorful.
|
||||
|
@ -84,5 +90,60 @@ public:
|
|||
|
||||
operator bool() const { return ok(); }
|
||||
};
|
||||
|
||||
/// A similar type to Rust's Result data structure. It either holds a value of
|
||||
/// type `T` successfully or holds a value of type `E` errorfully. It is
|
||||
/// designed to be used in situations which the return value of a function might
|
||||
/// contains some errors. The official way to use this type is to use the
|
||||
/// factory functions `Success` and `Error`. For example:
|
||||
///
|
||||
/// \code
|
||||
/// auto successfulResult = Result<int>::Success(3);
|
||||
/// auto notOkResult = Result<int>::Error(SomeLLVMError());
|
||||
// \endcode
|
||||
///
|
||||
/// In order check for a value being errorful or successful checkout the `ok`
|
||||
/// method or simply use the value as a conditiona.
|
||||
// template <typename T, typename E = llvm::Error> class SharedResult {
|
||||
|
||||
// // The actual data container
|
||||
// std::variant<std::shared_ptr<T>, E> contents;
|
||||
|
||||
// /// The main constructor which we made private to avoid ambiguousness in
|
||||
// /// input type. `Success` and `Error` call this ctor.
|
||||
// template <typename InPlace, typename Content>
|
||||
// SharedResult(InPlace i, Content &&c) : contents(i,
|
||||
// std::forward<Content>(c)){};
|
||||
|
||||
// public:
|
||||
// /// Create a succesfull result with the given value of type `T`.
|
||||
// static SharedResult Success(std::shared_ptr<T> v) {
|
||||
// return Result(std::in_place_index_t<0>(), v);
|
||||
// }
|
||||
|
||||
// /// Create an errorful result with the given value of type `E` (default
|
||||
// /// `llvm::Error`).
|
||||
// static SharedResult Error(E e) {
|
||||
// return Result(std::in_place_index_t<1>(), std::move(e));
|
||||
// }
|
||||
|
||||
// // using std::get, it'll throw if contents doesn't contain what you ask for
|
||||
|
||||
// /// Return the value if it's successful otherwise throw an error
|
||||
// T &getValue() { return std::get<0>(contents); };
|
||||
|
||||
// /// Return the error value if it's errorful otherwise throw an error
|
||||
// E &getError() { return std::get<1>(contents); };
|
||||
|
||||
// const T &getValue() const { return std::get<0>(contents); }
|
||||
// const E &getError() const { return std::get<1>(contents); }
|
||||
|
||||
// /// Return the a boolean value indicating whether the value is succesful
|
||||
// /// or errorful.
|
||||
// bool ok() const { return std::holds_alternative<T>(contents); };
|
||||
|
||||
// operator bool() const { return ok(); }
|
||||
// };
|
||||
|
||||
} // namespace serene
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,7 @@ set(HEADER_LIST
|
|||
"${INCLUDE_DIR}/serene/reader/reader.h"
|
||||
"${INCLUDE_DIR}/serene/reader/location.h"
|
||||
"${INCLUDE_DIR}/serene/reader/errors.h"
|
||||
"${INCLUDE_DIR}/serene/reader/semantics.h"
|
||||
|
||||
"${INCLUDE_DIR}/serene/errors.h"
|
||||
"${INCLUDE_DIR}/serene/errors/error.h"
|
||||
|
@ -52,6 +53,7 @@ add_library(serene
|
|||
reader/reader.cpp
|
||||
reader/location.cpp
|
||||
reader/errors.cpp
|
||||
reader/semantics.cpp
|
||||
|
||||
# IR
|
||||
sir/sir.cpp
|
||||
|
|
|
@ -23,10 +23,20 @@
|
|||
*/
|
||||
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
||||
namespace serene {
|
||||
namespace exprs {
|
||||
|
||||
void dump(ast &tree) {
|
||||
std::string result = "";
|
||||
|
||||
// for (auto &node : tree) {
|
||||
// result = llvm::formatv("{0} {1}", result, node->toString());
|
||||
// }
|
||||
|
||||
llvm::outs() << result << "#\n";
|
||||
};
|
||||
// template <typename T, typename... Args>
|
||||
// T* make(Args &&...args) {
|
||||
// return new T(std::forward<Args>(args)...);
|
||||
|
|
|
@ -24,17 +24,20 @@
|
|||
|
||||
#include "serene/exprs/list.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include <iterator>
|
||||
|
||||
namespace serene {
|
||||
namespace exprs {
|
||||
|
||||
List::List(const List &l) : Expression(l.location){};
|
||||
List::List(const reader::LocationRange &loc, node e) : Expression(loc) {
|
||||
List::List(const reader::LocationRange &loc, node &e) : Expression(loc) {
|
||||
elements.push_back(std::move(e));
|
||||
};
|
||||
|
||||
List::List(const reader::LocationRange &loc, llvm::ArrayRef<node> elems)
|
||||
: Expression(loc), elements(elems.begin(), elems.end()){};
|
||||
List::List(const reader::LocationRange &loc, llvm::MutableArrayRef<node> elems)
|
||||
: Expression(loc) {
|
||||
std::move(elems.begin(), elems.end(), elements.begin());
|
||||
};
|
||||
|
||||
ExprType List::getType() const { return ExprType::List; };
|
||||
std::string List::toString() const {
|
||||
|
@ -50,13 +53,13 @@ std::string List::toString() const {
|
|||
};
|
||||
|
||||
maybe_node List::analyze(reader::SemanticContext &ctx) {
|
||||
return Result<node>::Success(node(this));
|
||||
return Result<node>::Success(node(std::move(this)));
|
||||
};
|
||||
|
||||
bool List::classof(const Expression *e) {
|
||||
return e->getType() == ExprType::List;
|
||||
};
|
||||
|
||||
void List::append(node n) { elements.push_back(n); }
|
||||
void List::append(node n) { elements.push_back(std::move(n)); }
|
||||
} // namespace exprs
|
||||
} // namespace serene
|
||||
|
|
|
@ -37,7 +37,7 @@ std::string Symbol::toString() const {
|
|||
}
|
||||
|
||||
maybe_node Symbol::analyze(reader::SemanticContext &ctx) {
|
||||
return Result<node>::Success(node(this));
|
||||
return Result<node>::Success(node(std::move(this)));
|
||||
};
|
||||
|
||||
bool Symbol::classof(const Expression *e) {
|
||||
|
|
|
@ -55,7 +55,7 @@ mlir::LogicalResult Namespace::setTree(exprs::ast &t) {
|
|||
if (initialized) {
|
||||
return mlir::failure();
|
||||
}
|
||||
this->tree = t;
|
||||
this->tree = std::move(t);
|
||||
this->initialized = true;
|
||||
return mlir::success();
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ exprs::node Reader::readSymbol() {
|
|||
// TODO: Replece this with a tranceback function or something to raise
|
||||
// synatx error.
|
||||
llvm::errs() << llvm::formatv(
|
||||
"Invalid character at the start of a symbol: '{}'\n", c);
|
||||
"Invalid character at the start of a symbol: '{0}'\n", c);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ exprs::node 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.
|
||||
llvm::Expected<exprs::ast> Reader::read() {
|
||||
exprs::maybe_ast Reader::read() {
|
||||
char c = getChar(true);
|
||||
|
||||
while (c != EOF) {
|
||||
|
@ -271,7 +271,7 @@ llvm::Expected<exprs::ast> Reader::read() {
|
|||
c = getChar(true);
|
||||
}
|
||||
|
||||
return this->ast;
|
||||
return Result<exprs::ast>::Success(std::move(this->ast));
|
||||
};
|
||||
|
||||
/// Reads the input into an AST and prints it out as string again.
|
||||
|
@ -280,10 +280,10 @@ void Reader::toString() {
|
|||
std::string result = "";
|
||||
|
||||
if (!maybeAst) {
|
||||
throw maybeAst.takeError();
|
||||
throw std::move(maybeAst.getError());
|
||||
}
|
||||
|
||||
exprs::ast ast = *maybeAst;
|
||||
exprs::ast ast = std::move(maybeAst.getValue());
|
||||
|
||||
for (auto &node : ast) {
|
||||
result = llvm::formatv("{0} {1}", result, node->toString());
|
||||
|
@ -294,7 +294,7 @@ void Reader::toString() {
|
|||
// in the reader as an AST.
|
||||
/// Each expression type (from the reader perspective) has a
|
||||
/// reader function.
|
||||
llvm::Expected<exprs::ast> FileReader::read() {
|
||||
exprs::maybe_ast FileReader::read() {
|
||||
|
||||
// TODO: Add support for relative path as well
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
|
||||
|
@ -304,7 +304,7 @@ llvm::Expected<exprs::ast> FileReader::read() {
|
|||
llvm::errs() << "Could not open input file: " << EC.message() << "\n";
|
||||
llvm::errs() << fmt::format("File: '{}'\n", file);
|
||||
llvm::errs() << "Use absolute path for now\n";
|
||||
return llvm::make_error<MissingFileError>(file);
|
||||
return Result<exprs::ast>::Error(llvm::make_error<MissingFileError>(file));
|
||||
}
|
||||
|
||||
reader->setInput(fileOrErr.get()->getBuffer().str());
|
||||
|
@ -317,10 +317,10 @@ void FileReader::toString() {
|
|||
exprs::ast ast;
|
||||
|
||||
if (!maybeAst) {
|
||||
throw maybeAst.takeError();
|
||||
throw std::move(maybeAst.getError());
|
||||
}
|
||||
|
||||
ast = *maybeAst;
|
||||
ast = std::move(maybeAst.getValue());
|
||||
|
||||
std::string result = "";
|
||||
for (auto &node : ast) {
|
||||
|
|
|
@ -26,21 +26,27 @@
|
|||
#include "serene/exprs/expression.h"
|
||||
|
||||
namespace serene::reader {
|
||||
exprs::ast Semantics::analyze(exprs::ast &inputAst) {
|
||||
exprs::maybe_ast Semantics::analyze(exprs::ast &inputAst) {
|
||||
// TODO: Fetch the current namespace from the JIT engine later and if it is
|
||||
// `nil` then the given `ast` has to start with a namespace definition.
|
||||
|
||||
exprs::node tmp;
|
||||
exprs::ast ast;
|
||||
|
||||
for (auto &element : inputAst) {
|
||||
auto maybeNode = element->analyze(context);
|
||||
|
||||
if (!maybeNode) {
|
||||
// TODO: Check the error type to see whether we can continue or not.
|
||||
// If not, raise otherwise push it to the exception queue and move on.
|
||||
auto err = maybeNode.takeError();
|
||||
throw err;
|
||||
return Result<exprs::ast>::Error(std::move(maybeNode.getError()));
|
||||
}
|
||||
tmp = std::move(maybeNode).getValue();
|
||||
llvm::outs() << "HERE\n" << tmp->toString() << " n\n";
|
||||
ast.push_back(std::move(tmp));
|
||||
}
|
||||
|
||||
return Result<exprs::ast>::Success(std::move(ast));
|
||||
};
|
||||
|
||||
}; // namespace serene::reader
|
||||
|
|
|
@ -37,7 +37,7 @@ TEST_CASE("Read numbers", "[reader]") {
|
|||
FAIL();
|
||||
}
|
||||
|
||||
auto ast = maybeAst.get();
|
||||
auto ast = std::move(maybeAst).getValue();
|
||||
REQUIRE_FALSE(ast.empty());
|
||||
CHECK(ast.front()->toString() == "<Number [loc: 0:1:1 | 0:1:1]: 3>");
|
||||
|
||||
|
@ -48,7 +48,7 @@ TEST_CASE("Read numbers", "[reader]") {
|
|||
FAIL();
|
||||
}
|
||||
|
||||
ast = maybeAst.get();
|
||||
ast = std::move(maybeAst.getValue());
|
||||
REQUIRE_FALSE(ast.empty());
|
||||
CHECK(ast.front()->toString() == "<Number [loc: 0:2:2 | 0:3:3]: -34>");
|
||||
|
||||
|
@ -59,7 +59,7 @@ TEST_CASE("Read numbers", "[reader]") {
|
|||
FAIL();
|
||||
}
|
||||
|
||||
ast = maybeAst.get();
|
||||
ast = std::move(maybeAst.getValue());
|
||||
REQUIRE_FALSE(ast.empty());
|
||||
CHECK(ast.front()->toString() == "<Number [loc: 0:2:2 | 0:7:7]: -3.5434>");
|
||||
|
||||
|
@ -70,7 +70,7 @@ TEST_CASE("Read numbers", "[reader]") {
|
|||
FAIL();
|
||||
}
|
||||
|
||||
ast = maybeAst.get();
|
||||
ast = std::move(maybeAst.getValue());
|
||||
REQUIRE(ast.size() == 3);
|
||||
CHECK(ast.front()->toString() == "<Number [loc: 0:1:1 | 0:6:6]: 444323>");
|
||||
CHECK(ast[1]->toString() == "<Number [loc: 0:8:8 | 0:11:11]: 2123>");
|
||||
|
@ -87,7 +87,7 @@ TEST_CASE("Read Lists and Symbols", "[reader]") {
|
|||
FAIL();
|
||||
}
|
||||
|
||||
auto ast = maybeAst.get();
|
||||
auto ast = std::move(maybeAst.getValue());
|
||||
REQUIRE_FALSE(ast.empty());
|
||||
CHECK(ast.front()->toString() ==
|
||||
"<List [loc: 0:0:0 | 0:5:5]: <Symbol [loc: 0:2:2 | 0:2:2]: x> <Number "
|
||||
|
@ -100,7 +100,7 @@ TEST_CASE("Read Lists and Symbols", "[reader]") {
|
|||
FAIL();
|
||||
}
|
||||
|
||||
ast = maybeAst.get();
|
||||
ast = std::move(maybeAst.getValue());
|
||||
REQUIRE_FALSE(ast.empty());
|
||||
CHECK(ast.front()->toString() ==
|
||||
"<List [loc: 0:0:0 | 0:11:11]: <Symbol [loc: 0:2:2 | 0:2:2]: x> <List "
|
||||
|
@ -114,7 +114,7 @@ TEST_CASE("Read Lists and Symbols", "[reader]") {
|
|||
FAIL();
|
||||
}
|
||||
|
||||
ast = maybeAst.get();
|
||||
ast = std::move(maybeAst.getValue());
|
||||
REQUIRE_FALSE(ast.empty());
|
||||
CHECK(ast.front()->toString() ==
|
||||
"<List [loc: 0:0:0 | 1:3:7]: <Symbol [loc: 0:2:2 | 0:2:2]: x> <Symbol "
|
||||
|
|
Loading…
Reference in New Issue