Add the read and print functionality to the repl
This commit is contained in:
parent
3fb6fb3740
commit
fc11896c28
1
dev.org
1
dev.org
|
@ -108,6 +108,7 @@ on ADF
|
|||
|
||||
* TODOs
|
||||
** Bootstrap*
|
||||
*** TODO Use =const= where ever it makes sense
|
||||
*** TODO Create different pass pipeline for different compilation phases
|
||||
So we can use them directly via command line, like -O1 for example
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ public:
|
|||
/// Insert the given `ns` into the context. The Context object is
|
||||
/// the owner of all the namespaces. The `ns` will overwrite any
|
||||
/// namespace with the same name.
|
||||
void insertNS(const std::shared_ptr<Namespace> &ns);
|
||||
void insertNS(NSPtr &ns);
|
||||
|
||||
/// Sets the n ame of the current namespace in the context and return
|
||||
/// a boolean indicating the status of this operation. The operation
|
||||
|
@ -107,8 +107,8 @@ public:
|
|||
Namespace &getCurrentNS();
|
||||
|
||||
/// Lookup the namespace with the give name in the current context and
|
||||
/// return a shared pointer to it or a `nullptr` in it doesn't exist.
|
||||
std::shared_ptr<Namespace> getNS(llvm::StringRef ns_name);
|
||||
/// return a pointer to it or a `nullptr` in it doesn't exist.
|
||||
Namespace *getNS(llvm::StringRef ns_name);
|
||||
|
||||
SereneContext()
|
||||
: pm(&mlirContext), diagEngine(makeDiagnosticEngine(*this)),
|
||||
|
@ -134,8 +134,8 @@ public:
|
|||
CompilationPhase getTargetPhase() { return targetPhase; };
|
||||
int getOptimizatioLevel();
|
||||
|
||||
NSPtr readNamespace(const std::string &name);
|
||||
NSPtr readNamespace(std::string name, reader::LocationRange loc);
|
||||
MaybeNS readNamespace(const std::string &name);
|
||||
MaybeNS readNamespace(const std::string &name, reader::LocationRange loc);
|
||||
|
||||
private:
|
||||
CompilationPhase targetPhase;
|
||||
|
@ -143,7 +143,7 @@ private:
|
|||
// The namespace table. Every namespace that needs to be compiled has
|
||||
// to register itself with the context and appear on this table.
|
||||
// This table acts as a cache as well.
|
||||
std::map<std::string, std::shared_ptr<Namespace>> namespaces;
|
||||
std::map<std::string, NSPtr> namespaces;
|
||||
|
||||
// Why string vs pointer? We might rewrite the namespace and
|
||||
// holding a pointer means that it might point to the old version
|
||||
|
|
|
@ -20,14 +20,18 @@
|
|||
#define SERENE_DIAGNOSTICS_H
|
||||
|
||||
#include "serene/errors/constants.h"
|
||||
#include "serene/errors/error.h"
|
||||
#include "serene/reader/location.h"
|
||||
#include "serene/source_mgr.h"
|
||||
|
||||
#include <serene/export.h>
|
||||
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <memory>
|
||||
#include <mlir/IR/Diagnostics.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace serene {
|
||||
class SereneContext;
|
||||
class DiagnosticEngine;
|
||||
|
@ -81,6 +85,9 @@ public:
|
|||
void emitSyntaxError(reader::LocationRange loc, errors::ErrorVariant &e,
|
||||
llvm::StringRef msg = "");
|
||||
|
||||
void emit(const errors::ErrorPtr &err);
|
||||
void emit(const errors::ErrorTree &errs);
|
||||
|
||||
/// Throw out an error with the given `msg` and terminate the execution
|
||||
void panic(llvm::StringRef msg);
|
||||
};
|
||||
|
@ -89,9 +96,11 @@ public:
|
|||
/// `SereneContext`
|
||||
std::unique_ptr<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx);
|
||||
|
||||
/// Throw out an error with the given `msg` and terminate the execution
|
||||
void panic(SereneContext &ctx, llvm::StringRef msg);
|
||||
/// Throw out an error with the given `msg` and terminate the execution.
|
||||
SERENE_EXPORT void panic(SereneContext &ctx, llvm::StringRef msg);
|
||||
|
||||
/// Throw the give `ErrorTree` \p errs and terminate the execution.
|
||||
SERENE_EXPORT void throwErrors(SereneContext &ctx, errors::ErrorTree &errs);
|
||||
} // namespace serene
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,13 @@
|
|||
namespace serene {
|
||||
namespace errors {
|
||||
|
||||
/// This enum represent the expression type and **not** the value type.
|
||||
enum class ErrType {
|
||||
Syntax,
|
||||
Semantic,
|
||||
Compile,
|
||||
};
|
||||
|
||||
enum ErrID {
|
||||
E0000 = 0,
|
||||
E0001,
|
||||
|
|
|
@ -19,23 +19,25 @@
|
|||
#ifndef SERENE_ERRORS_ERROR_H
|
||||
#define SERENE_ERRORS_ERROR_H
|
||||
|
||||
#include "serene/context.h"
|
||||
#include "serene/errors/constants.h"
|
||||
#include "serene/errors/traits.h"
|
||||
#include "serene/reader/location.h"
|
||||
#include "serene/reader/traits.h"
|
||||
#include "serene/traits.h"
|
||||
//#include "serene/exprs/expression.h"
|
||||
#include <llvm/Support/Error.h>
|
||||
|
||||
#include <llvm/ADT/Optional.h>
|
||||
|
||||
namespace serene::reader {
|
||||
class LoccationRange;
|
||||
} // namespace serene::reader
|
||||
|
||||
namespace serene::errors {
|
||||
class Error;
|
||||
|
||||
/// This enum represent the expression type and **not** the value type.
|
||||
enum class ErrType {
|
||||
Syntax,
|
||||
Semantic,
|
||||
Compile,
|
||||
};
|
||||
using ErrorPtr = std::shared_ptr<errors::Error>;
|
||||
|
||||
// tree? Yupe, Errors can be stackable which makes a vector of them a tree
|
||||
using ErrorTree = std::vector<ErrorPtr>;
|
||||
using OptionalErrors = llvm::Optional<ErrorTree>;
|
||||
|
||||
/// This data structure represent the Lisp error. This type of expression
|
||||
/// doesn't show up in the AST but the compiler might rewrite the AST
|
||||
|
@ -56,10 +58,21 @@ public:
|
|||
std::string toString() const;
|
||||
reader::LocationRange &where();
|
||||
ErrorVariant *getVariant();
|
||||
std::string getMessage();
|
||||
std::string &getMessage();
|
||||
~Error() = default;
|
||||
};
|
||||
|
||||
/// Creates a new Error in the give location \p loc, with the given
|
||||
/// variant \p and an optional message \p msg and retuns a shared ptr
|
||||
/// to the error. This is the official API to make errors.
|
||||
ErrorPtr makeError(reader::LocationRange &loc, ErrorVariant &err,
|
||||
llvm::StringRef msg = "msg");
|
||||
|
||||
/// Creates a new ErrorTree out of a new Error that creats from the input
|
||||
/// argument and pass them to `makeError` function.
|
||||
ErrorTree makeErrorTree(reader::LocationRange &loc, ErrorVariant &err,
|
||||
llvm::StringRef msg = "msg");
|
||||
|
||||
}; // namespace serene::errors
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#ifndef SERENE_ERRORS_TRAITS_H
|
||||
#define SERENE_ERRORS_TRAITS_H
|
||||
|
||||
#include "serene/context.h"
|
||||
#include "serene/errors/constants.h"
|
||||
#include "serene/traits.h"
|
||||
|
||||
|
|
|
@ -37,16 +37,11 @@ namespace exprs {
|
|||
|
||||
class Expression;
|
||||
|
||||
using Node = std::shared_ptr<Expression>;
|
||||
using ErrorPtr = std::shared_ptr<errors::Error>;
|
||||
|
||||
// tree? Yupe, Errors can be stackable which makes a vector of them a tree
|
||||
using ErrorTree = std::vector<ErrorPtr>;
|
||||
|
||||
using MaybeNode = Result<Node, ErrorTree>;
|
||||
using Node = std::shared_ptr<Expression>;
|
||||
using MaybeNode = Result<Node, errors::ErrorTree>;
|
||||
|
||||
using Ast = std::vector<Node>;
|
||||
using MaybeAst = Result<Ast, ErrorTree>;
|
||||
using MaybeAst = Result<Ast, errors::ErrorTree>;
|
||||
|
||||
static auto EmptyNode = MaybeNode::success(nullptr);
|
||||
|
||||
|
@ -118,8 +113,9 @@ std::shared_ptr<T> makeAndCast(Args &&...args) {
|
|||
// of a `Result`. It should be useds where every we want to return a `MaybeNode`
|
||||
/// successfully
|
||||
template <typename T, typename... Args>
|
||||
Result<Node, ErrorTree> makeSuccessfulNode(Args &&...args) {
|
||||
return Result<Node, ErrorTree>::success(make<T>(std::forward<Args>(args)...));
|
||||
Result<Node, errors::ErrorTree> makeSuccessfulNode(Args &&...args) {
|
||||
return Result<Node, errors::ErrorTree>::success(
|
||||
make<T>(std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
/// The hlper function to create an Errorful `Result<T,...>` (`T` would be
|
||||
|
@ -127,10 +123,10 @@ Result<Node, ErrorTree> makeSuccessfulNode(Args &&...args) {
|
|||
/// passing any argument to this function to the `serene::errors::Error`
|
||||
/// constructor.
|
||||
template <typename T, typename... Args>
|
||||
Result<T, ErrorTree> makeErrorful(Args &&...args) {
|
||||
std::vector<ErrorPtr> v{
|
||||
Result<T, errors::ErrorTree> makeErrorful(Args &&...args) {
|
||||
std::vector<errors::ErrorPtr> v{
|
||||
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
|
||||
return Result<T, ErrorTree>::error(v);
|
||||
return Result<T, errors::ErrorTree>::error(v);
|
||||
};
|
||||
|
||||
/// The hlper function to create an Error node (The failure case of a MaybeNod)
|
||||
|
@ -138,7 +134,7 @@ Result<T, ErrorTree> makeErrorful(Args &&...args) {
|
|||
/// the `serene::errors::Error` constructor.
|
||||
template <typename... Args>
|
||||
MaybeNode makeErrorNode(Args &&...args) {
|
||||
std::vector<ErrorPtr> v{
|
||||
std::vector<errors::ErrorPtr> v{
|
||||
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
|
||||
return MaybeNode::error(v);
|
||||
};
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "serene/errors.h"
|
||||
#include "serene/export.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/namespace.h"
|
||||
#include "serene/slir/generatable.h"
|
||||
#include "serene/utils.h"
|
||||
|
||||
|
@ -162,6 +164,9 @@ public:
|
|||
void registerSymbols(
|
||||
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
|
||||
symbolMap);
|
||||
|
||||
std::unique_ptr<exprs::Expression> eval(SereneContext &ctx,
|
||||
std::string input);
|
||||
};
|
||||
} // namespace serene
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#define SERENE_NAMESPACE_H
|
||||
|
||||
#include "serene/environment.h"
|
||||
#include "serene/errors/error.h"
|
||||
#include "serene/export.h"
|
||||
#include "serene/slir/generatable.h"
|
||||
#include "serene/traits.h"
|
||||
|
@ -98,8 +99,8 @@ public:
|
|||
|
||||
/// Expand the current tree of the namespace with the given \p ast by
|
||||
/// semantically analazing it first. If the give \p ast in not valid
|
||||
/// it will emit an error.
|
||||
mlir::LogicalResult expandTree(exprs::Ast &ast);
|
||||
/// it will return analysis errors.
|
||||
errors::OptionalErrors expandTree(exprs::Ast &ast);
|
||||
|
||||
/// Increase the function counter by one
|
||||
uint nextFnCounter();
|
||||
|
@ -127,10 +128,12 @@ public:
|
|||
};
|
||||
|
||||
using NSPtr = std::shared_ptr<Namespace>;
|
||||
|
||||
using MaybeNS = Result<NSPtr, errors::ErrorTree>;
|
||||
/// Create a naw namespace with the given `name` and optional `filename` and
|
||||
/// return a shared pointer to it in the given Serene context. If the
|
||||
/// `setCurrent` argument is set to true, the created NS will become the curret
|
||||
/// namespace in the context
|
||||
/// `setCurrent` argument is set to true, the created NS will become the
|
||||
/// curret namespace in the context
|
||||
SERENE_EXPORT NSPtr makeNamespace(SereneContext &ctx, llvm::StringRef name,
|
||||
llvm::Optional<llvm::StringRef> filename,
|
||||
bool setCurrent = true);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "serene/exprs/expression.h"
|
||||
|
||||
namespace serene::reader {
|
||||
using AnalyzeResult = Result<exprs::Ast, std::vector<exprs::ErrorPtr>>;
|
||||
using AnalyzeResult = Result<exprs::Ast, std::vector<errors::ErrorPtr>>;
|
||||
/// The entry point to the Semantic analysis phase. It calls the `analyze`
|
||||
/// method of each node in the given AST and creates a new AST that contains a
|
||||
/// more comprehensive set of nodes in a semantically correct AST. If the
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "serene/config.h"
|
||||
#include "serene/context.h"
|
||||
#include "serene/export.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/source_mgr.h"
|
||||
|
||||
namespace serene {
|
||||
|
@ -38,5 +39,42 @@ SERENE_EXPORT void registerSereneCLOptions();
|
|||
/// Applies the global compiler options on the give \p SereneContext. This
|
||||
/// function has to be called after `llvm::cl::ParseCommandLineOptions`.
|
||||
SERENE_EXPORT void applySereneCLOptions(SereneContext &ctx);
|
||||
|
||||
/// Reads the the given \p input as a Serene source code in the given
|
||||
/// \c SereneContext \p ctx and returns the possible AST tree of the input or an
|
||||
/// error otherwise.
|
||||
///
|
||||
/// In case of an error Serene will throw the error messages vis the diagnostic
|
||||
/// engine as well and the error that this function returns will be the generic
|
||||
/// error message.
|
||||
///
|
||||
/// Be aware than this function reads the input in the context of the current
|
||||
/// namespace. So for example if the input is somthing like:
|
||||
///
|
||||
/// (ns example.code) ....
|
||||
///
|
||||
/// and the current ns is `user` then if there is a syntax error in the input
|
||||
/// the error will be reported under the `user` ns. This is logical because
|
||||
/// this function reads the code and not evaluate it. the `ns` form has to be
|
||||
/// evaluated in order to change the ns.
|
||||
SERENE_EXPORT exprs::MaybeAst read(SereneContext &ctx, std::string &input);
|
||||
|
||||
/// Evaluates the given AST form \p input in the given \c SereneContext \p ctx
|
||||
/// and retuns a new expression as the result or a possible error.
|
||||
///
|
||||
/// In case of an error Serene will throw the error messages vis the diagnostic
|
||||
/// engine as well and the error that this function returns will be the
|
||||
/// generic error message.
|
||||
// SERENE_EXPORT exprs::MaybeNode eval(SereneContext &ctx, exprs::Ast input);
|
||||
|
||||
// TODO: Return a Serene String type instead of the std::string
|
||||
// TODO: Create an overload to get a stream instead of the result string
|
||||
/// Prints the given AST form \p input in the given \c SereneContext \p ctx
|
||||
/// into the given \p result.
|
||||
/// Note: print is a lisp action. Don't confuse it with a print function such
|
||||
/// as `println`.
|
||||
SERENE_EXPORT void print(SereneContext &ctx, const exprs::Ast &input,
|
||||
std::string &result);
|
||||
|
||||
} // namespace serene
|
||||
#endif
|
||||
|
|
|
@ -28,10 +28,11 @@
|
|||
#include <llvm/Support/ErrorOr.h>
|
||||
#include <llvm/Support/MemoryBuffer.h>
|
||||
#include <llvm/Support/SourceMgr.h>
|
||||
#include <memory>
|
||||
#include <mlir/IR/Diagnostics.h>
|
||||
#include <mlir/Support/Timing.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#define SMGR_LOG(...) \
|
||||
DEBUG_WITH_TYPE("sourcemgr", llvm::dbgs() \
|
||||
<< "[SMGR]: " << __VA_ARGS__ << "\n");
|
||||
|
@ -173,15 +174,15 @@ public:
|
|||
reader::LocationRange includeLoc);
|
||||
|
||||
/// Lookup for a file containing the namespace definition of with given
|
||||
/// namespace name \p name and throw an error. In case that the file exists,
|
||||
/// use the parser to read the file and create an AST from it. Then create a
|
||||
/// namespace, set the its AST to the AST that we just read from the file and
|
||||
/// return a shared pointer to the namespace.
|
||||
/// namespace name \p name. In case that the file exists, it returns an
|
||||
/// `ErrorTree`. It will use the parser to read the file and create an AST
|
||||
/// from it. Then create a namespace, set the its AST to the AST that we just
|
||||
/// read from the file and return a shared pointer to the namespace.
|
||||
///
|
||||
/// \p importLoc is a location in the source code where the give namespace is
|
||||
/// imported.
|
||||
NSPtr readNamespace(SereneContext &ctx, std::string name,
|
||||
reader::LocationRange importLoc);
|
||||
MaybeNS readNamespace(SereneContext &ctx, std::string name,
|
||||
reader::LocationRange importLoc);
|
||||
};
|
||||
|
||||
}; // namespace serene
|
||||
|
|
|
@ -29,13 +29,14 @@
|
|||
|
||||
namespace serene {
|
||||
|
||||
void SereneContext::insertNS(const std::shared_ptr<Namespace> &ns) {
|
||||
namespaces[ns->name] = ns;
|
||||
void SereneContext::insertNS(NSPtr &ns) {
|
||||
auto nsName = ns->name;
|
||||
namespaces[nsName] = ns;
|
||||
};
|
||||
|
||||
std::shared_ptr<Namespace> SereneContext::getNS(llvm::StringRef ns_name) {
|
||||
Namespace *SereneContext::getNS(llvm::StringRef ns_name) {
|
||||
if (namespaces.count(ns_name.str()) != 0) {
|
||||
return namespaces[ns_name.str()];
|
||||
return namespaces[ns_name.str()].get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -90,14 +91,14 @@ int SereneContext::getOptimizatioLevel() {
|
|||
return 3;
|
||||
}
|
||||
|
||||
NSPtr SereneContext::readNamespace(const std::string &name) {
|
||||
MaybeNS SereneContext::readNamespace(const std::string &name) {
|
||||
auto loc = reader::LocationRange::UnknownLocation(name);
|
||||
|
||||
return readNamespace(name, loc);
|
||||
};
|
||||
|
||||
NSPtr SereneContext::readNamespace(std::string name,
|
||||
reader::LocationRange loc) {
|
||||
MaybeNS SereneContext::readNamespace(const std::string &name,
|
||||
reader::LocationRange loc) {
|
||||
return sourceManager.readNamespace(*this, std::move(name), loc);
|
||||
}
|
||||
|
||||
|
|
|
@ -203,8 +203,24 @@ std::unique_ptr<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx) {
|
|||
return std::make_unique<DiagnosticEngine>(ctx);
|
||||
}
|
||||
|
||||
void DiagnosticEngine::emit(const errors::ErrorPtr &err) {
|
||||
UNUSED(ctx);
|
||||
// TODO: create a diag and print it
|
||||
llvm::errs() << err->toString() << "\n";
|
||||
};
|
||||
|
||||
void DiagnosticEngine::emit(const errors::ErrorTree &errs) {
|
||||
for (const auto &e : errs) {
|
||||
emit(e);
|
||||
}
|
||||
};
|
||||
|
||||
void panic(SereneContext &ctx, llvm::StringRef msg) {
|
||||
ctx.diagEngine->panic(msg);
|
||||
};
|
||||
|
||||
void throwErrors(SereneContext &ctx, errors::ErrorTree &errs) {
|
||||
ctx.diagEngine->emit(errs);
|
||||
};
|
||||
|
||||
} // namespace serene
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <llvm/Support/FormatVariadic.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace serene {
|
||||
namespace errors {
|
||||
|
||||
|
@ -31,7 +33,18 @@ reader::LocationRange &Error::where() { return this->location; };
|
|||
|
||||
ErrorVariant *Error::getVariant() { return this->variant; }
|
||||
|
||||
std::string Error::getMessage() { return this->message; }
|
||||
std::string &Error::getMessage() { return this->message; }
|
||||
|
||||
ErrorPtr makeError(reader::LocationRange &loc, ErrorVariant &err,
|
||||
llvm::StringRef msg) {
|
||||
return std::make_shared<Error>(loc, err, msg);
|
||||
};
|
||||
|
||||
ErrorTree makeErrorTree(reader::LocationRange &loc, ErrorVariant &err,
|
||||
llvm::StringRef msg) {
|
||||
std::vector errs{makeError(loc, err, msg)};
|
||||
return errs;
|
||||
};
|
||||
|
||||
} // namespace errors
|
||||
} // namespace serene
|
||||
|
|
|
@ -34,11 +34,12 @@
|
|||
#include <llvm/ADT/StringRef.h>
|
||||
#include <llvm/Support/FormatVariadic.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <memory>
|
||||
#include <mlir/IR/Builders.h>
|
||||
#include <mlir/IR/BuiltinOps.h>
|
||||
#include <mlir/IR/Verifier.h>
|
||||
#include <mlir/Support/LogicalResult.h>
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
|
@ -61,12 +62,12 @@ void Namespace::enqueueError(llvm::StringRef e) const {
|
|||
|
||||
exprs::Ast &Namespace::getTree() { return this->tree; }
|
||||
|
||||
mlir::LogicalResult Namespace::expandTree(exprs::Ast &ast) {
|
||||
errors::OptionalErrors Namespace::expandTree(exprs::Ast &ast) {
|
||||
|
||||
if (ctx.getTargetPhase() == CompilationPhase::Parse) {
|
||||
// we just want the raw AST
|
||||
this->tree.insert(this->tree.end(), ast.begin(), ast.end());
|
||||
return mlir::success();
|
||||
return llvm::None;
|
||||
}
|
||||
|
||||
// Run the semantic analyer on the ast and then if everything
|
||||
|
@ -74,13 +75,12 @@ mlir::LogicalResult Namespace::expandTree(exprs::Ast &ast) {
|
|||
auto maybeAst = reader::analyze(ctx, ast);
|
||||
|
||||
if (!maybeAst) {
|
||||
enqueueError("Semantic analysis failed!");
|
||||
return mlir::failure();
|
||||
return maybeAst.getError();
|
||||
}
|
||||
|
||||
auto semanticAst = std::move(maybeAst.getValue());
|
||||
this->tree.insert(this->tree.end(), semanticAst.begin(), semanticAst.end());
|
||||
return mlir::success();
|
||||
return llvm::None;
|
||||
}
|
||||
|
||||
uint Namespace::nextFnCounter() { return fn_counter++; };
|
||||
|
@ -154,11 +154,12 @@ MaybeModule Namespace::compileToLLVM() {
|
|||
|
||||
Namespace::~Namespace(){};
|
||||
|
||||
std::shared_ptr<Namespace>
|
||||
makeNamespace(SereneContext &ctx, llvm::StringRef name,
|
||||
llvm::Optional<llvm::StringRef> filename, bool setCurrent) {
|
||||
NSPtr makeNamespace(SereneContext &ctx, llvm::StringRef name,
|
||||
llvm::Optional<llvm::StringRef> filename, bool setCurrent) {
|
||||
auto nsPtr = std::make_shared<Namespace>(ctx, name, filename);
|
||||
|
||||
ctx.insertNS(nsPtr);
|
||||
|
||||
if (setCurrent) {
|
||||
if (!ctx.setCurrentNS(nsPtr->name)) {
|
||||
throw std::runtime_error("Couldn't set the current NS");
|
||||
|
|
|
@ -27,7 +27,7 @@ AnalyzeResult analyze(serene::SereneContext &ctx, 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.
|
||||
|
||||
std::vector<exprs::ErrorPtr> errors;
|
||||
errors::ErrorTree errors;
|
||||
exprs::Ast ast;
|
||||
|
||||
for (auto &element : inputAst) {
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
|
||||
#include "serene/serene.h"
|
||||
|
||||
#include "serene/diagnostics.h"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/reader/reader.h"
|
||||
|
||||
#include <llvm/ADT/None.h>
|
||||
#include <llvm/Support/TargetSelect.h>
|
||||
|
||||
namespace serene {
|
||||
|
@ -81,4 +86,24 @@ void applySereneCLOptions(SereneContext &ctx) {
|
|||
#endif
|
||||
}
|
||||
|
||||
SERENE_EXPORT exprs::MaybeAst read(SereneContext &ctx, std::string &input) {
|
||||
auto ¤tNS = ctx.getCurrentNS();
|
||||
auto filename =
|
||||
!currentNS.filename.hasValue()
|
||||
? llvm::None
|
||||
: llvm::Optional<llvm::StringRef>(currentNS.filename.getValue());
|
||||
|
||||
return reader::read(ctx, input, currentNS.name, filename);
|
||||
};
|
||||
|
||||
// SERENE_EXPORT exprs::MaybeNode eval(SereneContext &ctx, exprs::Ast input){
|
||||
|
||||
// };
|
||||
|
||||
SERENE_EXPORT void print(SereneContext &ctx, const exprs::Ast &input,
|
||||
std::string &result) {
|
||||
UNUSED(ctx);
|
||||
result = exprs::astToString(&input);
|
||||
};
|
||||
|
||||
} // namespace serene
|
||||
|
|
|
@ -31,12 +31,13 @@
|
|||
#include "serene/reader/semantics.h"
|
||||
#include "serene/utils.h"
|
||||
|
||||
#include <system_error>
|
||||
|
||||
#include <llvm/Support/FormatVariadic.h>
|
||||
#include <llvm/Support/Locale.h>
|
||||
#include <llvm/Support/MemoryBufferRef.h>
|
||||
#include <llvm/Support/Path.h>
|
||||
#include <mlir/Support/LogicalResult.h>
|
||||
#include <system_error>
|
||||
|
||||
namespace serene {
|
||||
|
||||
|
@ -77,8 +78,8 @@ SourceMgr::findFileInLoadPath(const std::string &name,
|
|||
return newBufOrErr;
|
||||
};
|
||||
|
||||
NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||
reader::LocationRange importLoc) {
|
||||
MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||
reader::LocationRange importLoc) {
|
||||
std::string importedFile;
|
||||
|
||||
SMGR_LOG("Attempt to load namespace: " + name);
|
||||
|
@ -86,9 +87,9 @@ NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
|||
|
||||
if (!newBufOrErr) {
|
||||
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name);
|
||||
ctx.diagEngine->emitSyntaxError(importLoc, errors::NSLoadError,
|
||||
llvm::StringRef(msg));
|
||||
return nullptr;
|
||||
auto err = errors::makeErrorTree(importLoc, errors::NSLoadError,
|
||||
llvm::StringRef(msg));
|
||||
return MaybeNS::error(err);
|
||||
}
|
||||
|
||||
auto bufferId = AddNewSourceBuffer(std::move(*newBufOrErr), importLoc);
|
||||
|
@ -97,11 +98,9 @@ NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
|||
|
||||
if (bufferId == 0) {
|
||||
auto msg = llvm::formatv("Couldn't add namespace '{0}'", name);
|
||||
// TODO: enqueue the error here
|
||||
ctx.diagEngine->emitSyntaxError(importLoc, errors::NSAddToSMError,
|
||||
llvm::StringRef(msg));
|
||||
|
||||
return nullptr;
|
||||
auto err = errors::makeErrorTree(importLoc, errors::NSAddToSMError,
|
||||
llvm::StringRef(msg));
|
||||
return MaybeNS::error(err);
|
||||
}
|
||||
|
||||
// Since we moved the buffer to be added as the source storage we
|
||||
|
@ -114,21 +113,17 @@ NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
|||
|
||||
if (!maybeAst) {
|
||||
SMGR_LOG("Couldn't Read namespace: " + name);
|
||||
// The code that is calling this function has to flush the dia engine, so we
|
||||
// don't have to emit an error
|
||||
return nullptr;
|
||||
return MaybeNS::error(maybeAst.getError());
|
||||
}
|
||||
|
||||
// Create the NS and set the AST
|
||||
auto ns =
|
||||
makeNamespace(ctx, name, llvm::Optional(llvm::StringRef(importedFile)));
|
||||
|
||||
if (mlir::failed(ns->expandTree(maybeAst.getValue()))) {
|
||||
auto errs = ns->expandTree(maybeAst.getValue());
|
||||
if (errs) {
|
||||
SMGR_LOG("Couldn't set the AST for namespace: " + name);
|
||||
// The code that is calling this function has to flush the dia engine, so we
|
||||
// don't have to emit an error
|
||||
|
||||
return nullptr;
|
||||
return MaybeNS::error(errs.getValue());
|
||||
}
|
||||
|
||||
return ns;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "serene/diagnostics.h"
|
||||
#include "serene/linenoise.h"
|
||||
#include "serene/serene.h"
|
||||
|
||||
|
@ -38,6 +39,7 @@ static std::string banner =
|
|||
|
||||
static std::string art = "\n";
|
||||
|
||||
// TODO: Change the default value to be OS agnostic
|
||||
static cl::opt<std::string>
|
||||
historyFile("h", cl::desc("The absolute path to the history file to use."),
|
||||
cl::value_desc("filename"), cl::init("~/.serene-repl.history"));
|
||||
|
@ -67,6 +69,7 @@ int main(int argc, char *argv[]) {
|
|||
while (true) {
|
||||
// Read line
|
||||
std::string line;
|
||||
std::string result;
|
||||
std::string prompt = ctx->getCurrentNS().name + "> ";
|
||||
|
||||
auto quit = linenoise::Readline(prompt.c_str(), line);
|
||||
|
@ -75,8 +78,15 @@ int main(int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
|
||||
llvm::outs() << "echo: '" << line << "'"
|
||||
<< "\n";
|
||||
auto maybeAst = serene::read(*ctx, line);
|
||||
|
||||
if (!maybeAst) {
|
||||
serene::throwErrors(*ctx, maybeAst.getError());
|
||||
continue;
|
||||
}
|
||||
|
||||
serene::print(*ctx, maybeAst.getValue(), result);
|
||||
llvm::outs() << result << "\n";
|
||||
|
||||
// Add text to history
|
||||
linenoise::AddHistory(line.c_str());
|
||||
|
|
|
@ -287,13 +287,16 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
auto runLoc = reader::LocationRange::UnknownLocation(inputNS);
|
||||
auto ns = ctx->sourceManager.readNamespace(*ctx, inputNS, runLoc);
|
||||
auto runLoc = reader::LocationRange::UnknownLocation(inputNS);
|
||||
auto maybeNS = ctx->sourceManager.readNamespace(*ctx, inputNS, runLoc);
|
||||
|
||||
if (!ns) {
|
||||
if (!maybeNS) {
|
||||
throwErrors(*ctx, maybeNS.getError());
|
||||
return (int)std::errc::no_such_file_or_directory;
|
||||
}
|
||||
|
||||
auto ns = maybeNS.getValue();
|
||||
|
||||
ctx->insertNS(ns);
|
||||
|
||||
switch (emitAction) {
|
||||
|
@ -303,6 +306,7 @@ int main(int argc, char *argv[]) {
|
|||
llvm::outs() << exprs::astToString(&ast) << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
case Action::DumpSLIR:
|
||||
case Action::DumpMLIR:
|
||||
case Action::DumpLIR: {
|
||||
|
|
Loading…
Reference in New Issue