Finish up the errors-backend and migrate serene's errs to llvm:
This commit is contained in:
parent
95e9edf61e
commit
64ee59fbc8
|
@ -227,7 +227,7 @@ public:
|
||||||
|
|
||||||
// TODO: Fix this by calling to the diag engine
|
// TODO: Fix this by calling to the diag engine
|
||||||
if (err) {
|
if (err) {
|
||||||
llvm::errs() << err.getValue().back()->getMessage() << "\n";
|
llvm::errs() << err << "\n";
|
||||||
serene::terminate(*ctx, 1);
|
serene::terminate(*ctx, 1);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
#ifndef SERENE_DIAGNOSTICS_H
|
#ifndef SERENE_DIAGNOSTICS_H
|
||||||
#define SERENE_DIAGNOSTICS_H
|
#define SERENE_DIAGNOSTICS_H
|
||||||
|
|
||||||
#include "serene/errors/constants.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/errors/error.h"
|
|
||||||
#include "serene/reader/location.h"
|
#include "serene/reader/location.h"
|
||||||
#include "serene/source_mgr.h"
|
#include "serene/source_mgr.h"
|
||||||
|
|
||||||
|
@ -51,16 +50,15 @@ class Diagnostic {
|
||||||
SereneContext &ctx;
|
SereneContext &ctx;
|
||||||
reader::LocationRange loc;
|
reader::LocationRange loc;
|
||||||
std::string fn;
|
std::string fn;
|
||||||
errors::ErrorVariant *err = nullptr;
|
llvm::Error *err = nullptr;
|
||||||
Type type = Type::Error;
|
Type type = Type::Error;
|
||||||
std::string message, lineContents;
|
std::string message, lineContents;
|
||||||
|
|
||||||
std::string getPrefix(llvm::StringRef prefix = "");
|
std::string getPrefix(llvm::StringRef prefix = "");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Diagnostic(SereneContext &ctx, reader::LocationRange loc,
|
Diagnostic(SereneContext &ctx, reader::LocationRange loc, llvm::Error *e,
|
||||||
errors::ErrorVariant *e, llvm::StringRef msg,
|
llvm::StringRef msg, llvm::StringRef fn = "")
|
||||||
llvm::StringRef fn = "")
|
|
||||||
: ctx(ctx), loc(loc), fn(fn), err(e), message(msg){};
|
: ctx(ctx), loc(loc), fn(fn), err(e), message(msg){};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -73,7 +71,7 @@ class DiagnosticEngine {
|
||||||
|
|
||||||
mlir::DiagnosticEngine &diagEngine;
|
mlir::DiagnosticEngine &diagEngine;
|
||||||
|
|
||||||
Diagnostic toDiagnostic(reader::LocationRange loc, errors::ErrorVariant &e,
|
Diagnostic toDiagnostic(reader::LocationRange loc, llvm::Error &e,
|
||||||
llvm::StringRef msg, llvm::StringRef fn = "");
|
llvm::StringRef msg, llvm::StringRef fn = "");
|
||||||
|
|
||||||
void print(llvm::raw_ostream &os, Diagnostic &d);
|
void print(llvm::raw_ostream &os, Diagnostic &d);
|
||||||
|
@ -82,11 +80,10 @@ public:
|
||||||
DiagnosticEngine(SereneContext &ctx);
|
DiagnosticEngine(SereneContext &ctx);
|
||||||
|
|
||||||
void enqueueError(llvm::StringRef msg);
|
void enqueueError(llvm::StringRef msg);
|
||||||
void emitSyntaxError(reader::LocationRange loc, errors::ErrorVariant &e,
|
void emitSyntaxError(reader::LocationRange loc, llvm::Error &e,
|
||||||
llvm::StringRef msg = "");
|
llvm::StringRef msg = "");
|
||||||
|
|
||||||
void emit(const errors::ErrorPtr &err);
|
void emit(const llvm::Error &err);
|
||||||
void emit(const errors::ErrorTree &errs);
|
|
||||||
|
|
||||||
/// Throw out an error with the given `msg` and terminate the execution
|
/// Throw out an error with the given `msg` and terminate the execution
|
||||||
void panic(llvm::StringRef msg);
|
void panic(llvm::StringRef msg);
|
||||||
|
@ -99,8 +96,8 @@ std::unique_ptr<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx);
|
||||||
/// Throw out an error with the given `msg` and terminate the execution.
|
/// Throw out an error with the given `msg` and terminate the execution.
|
||||||
SERENE_EXPORT void panic(SereneContext &ctx, llvm::StringRef msg);
|
SERENE_EXPORT void panic(SereneContext &ctx, llvm::StringRef msg);
|
||||||
|
|
||||||
/// Throw the give `ErrorTree` \p errs and terminate the execution.
|
/// Throw the give `llvm::Error` \p errs to the stderr.
|
||||||
SERENE_EXPORT void throwErrors(SereneContext &ctx, errors::ErrorTree &errs);
|
SERENE_EXPORT void throwErrors(SereneContext &ctx, llvm::Error &errs);
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,21 @@
|
||||||
#ifndef SERENE_ERRORS_H
|
#ifndef SERENE_ERRORS_H
|
||||||
#define SERENE_ERRORS_H
|
#define SERENE_ERRORS_H
|
||||||
|
|
||||||
|
#include "serene/errors/base.h"
|
||||||
#include "serene/errors/errc.h"
|
#include "serene/errors/errc.h"
|
||||||
#include "serene/errors/error.h"
|
|
||||||
|
#define GET_CLASS_DEFS
|
||||||
|
#include "serene/errors/errs.h.inc"
|
||||||
|
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
|
|
||||||
|
namespace serene::errors {
|
||||||
|
|
||||||
|
template <typename E, typename... Args>
|
||||||
|
llvm::Error makeError(Args &&...args) {
|
||||||
|
return llvm::make_error<E>(std::forward<Args>(args)...);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace serene::errors
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,37 +24,62 @@
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
#include <llvm/Support/Error.h>
|
#include <llvm/Support/Error.h>
|
||||||
|
#include <llvm/Support/FormatVariadic.h>
|
||||||
|
|
||||||
namespace serene::errors {
|
namespace serene::errors {
|
||||||
|
|
||||||
template <typename T>
|
struct ErrorVariant {
|
||||||
class SereneError : public llvm::ErrorInfo<T> {
|
int id;
|
||||||
|
const std::string title;
|
||||||
|
const std::string desc;
|
||||||
|
const std::string help;
|
||||||
|
|
||||||
|
static ErrorVariant make(int id, const char *t, const char *d,
|
||||||
|
const char *h) {
|
||||||
|
return ErrorVariant(id, t, d, h);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
ErrorVariant(int id, const char *t, const char *d, const char *h)
|
||||||
|
: id(id), title(t), desc(d), help(h){};
|
||||||
|
};
|
||||||
|
|
||||||
|
class SereneError : public llvm::ErrorInfoBase {
|
||||||
reader::LocationRange location;
|
reader::LocationRange location;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int ID = -1;
|
static const int ID = -1;
|
||||||
|
|
||||||
void log(llvm::raw_ostream &os) const { os << msg; };
|
void log(llvm::raw_ostream &os) const override { os << msg; };
|
||||||
std::string message() const override { return msg; };
|
std::string message() const override { return msg; };
|
||||||
std::string &getTitle() const { return T::title; };
|
|
||||||
std::string &getDesc() const { return T::description; };
|
std::error_code convertToErrorCode() const override {
|
||||||
std::error_code convertToErrorCode() const { return std::error_code(); };
|
return std::error_code();
|
||||||
|
};
|
||||||
|
|
||||||
SereneError(reader::LocationRange &loc, std::string &msg)
|
SereneError(reader::LocationRange &loc, std::string &msg)
|
||||||
: location(loc), msg(msg){};
|
: location(loc), msg(msg){};
|
||||||
|
|
||||||
|
SereneError(reader::LocationRange &loc, const char *msg)
|
||||||
|
: location(loc), msg(msg){};
|
||||||
|
|
||||||
|
SereneError(reader::LocationRange &loc, llvm::StringRef msg)
|
||||||
|
: location(loc), msg(msg.str()){};
|
||||||
|
|
||||||
|
SereneError(reader::LocationRange &loc) : location(loc){};
|
||||||
|
|
||||||
|
SereneError(SereneError &e) = delete;
|
||||||
|
|
||||||
reader::LocationRange &where() { return location; };
|
reader::LocationRange &where() { return location; };
|
||||||
|
|
||||||
static const void *classID() { return &T::ID; }
|
static const void *classID() { return &ID; }
|
||||||
|
|
||||||
bool isA(const void *const id) const override {
|
bool isA(const void *const id) const override {
|
||||||
// the check with -1 is a shortcut for us to figure
|
return id == classID() || llvm::ErrorInfoBase::isA(id);
|
||||||
// out whether we're dealing with an Serene error or
|
|
||||||
// LLVM error
|
|
||||||
return *(const int *)id == -1 || id == classID() ||
|
|
||||||
llvm::ErrorInfoBase::isA(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~SereneError() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace serene::errors
|
}; // namespace serene::errors
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
/* -*- C++ -*-
|
|
||||||
* Serene Programming Language
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, version 2.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SERENE_ERRORS_ERROR_H
|
|
||||||
#define SERENE_ERRORS_ERROR_H
|
|
||||||
|
|
||||||
#include "serene/errors/constants.h"
|
|
||||||
#include "serene/errors/errs.h.inc"
|
|
||||||
#include "serene/errors/traits.h"
|
|
||||||
#include "serene/reader/traits.h"
|
|
||||||
#include "serene/traits.h"
|
|
||||||
|
|
||||||
#include <serene/export.h>
|
|
||||||
|
|
||||||
#include <llvm/ADT/Optional.h>
|
|
||||||
|
|
||||||
namespace serene::reader {
|
|
||||||
class LocationRange;
|
|
||||||
} // namespace serene::reader
|
|
||||||
|
|
||||||
namespace serene::errors {
|
|
||||||
class Error;
|
|
||||||
|
|
||||||
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
|
|
||||||
/// to contains error expressions
|
|
||||||
class SERENE_EXPORT Error
|
|
||||||
: public WithTrait<Error, IError, reader::ILocatable, serene::IDebuggable> {
|
|
||||||
reader::LocationRange location;
|
|
||||||
ErrorVariant *variant;
|
|
||||||
std::string message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Error(reader::LocationRange &loc, ErrorVariant &err, llvm::StringRef msg)
|
|
||||||
: location(loc), variant(&err), message(msg){};
|
|
||||||
|
|
||||||
Error(reader::LocationRange &loc, ErrorVariant &err)
|
|
||||||
: location(loc), variant(&err){};
|
|
||||||
|
|
||||||
std::string toString() const;
|
|
||||||
reader::LocationRange &where();
|
|
||||||
ErrorVariant *getVariant();
|
|
||||||
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
|
|
|
@ -1,23 +1,76 @@
|
||||||
|
|
||||||
class Error<string _title = "", string _desc = ""> {
|
|
||||||
string title = _title;
|
class Error<string _desc = "", string _help = ""> {
|
||||||
string description = _desc;
|
string desc = _desc;
|
||||||
|
string help = _help;
|
||||||
}
|
}
|
||||||
|
|
||||||
def Err : Error<"Err1 titel"> {
|
// Examples of how to define a new error
|
||||||
let description = [{
|
// def Err : Error<"Err1 titel"> {
|
||||||
err1
|
// let description = [{
|
||||||
multiline
|
// err1
|
||||||
desc}];
|
// multiline
|
||||||
}
|
// desc}];
|
||||||
|
// }
|
||||||
|
|
||||||
def Err2 : Error {
|
// def Err2 : Error {
|
||||||
let title = "err 2 titel";
|
// let title = "err 2 titel";
|
||||||
let description = "err2 desc";
|
// let description = "err2 desc";
|
||||||
}
|
// }
|
||||||
|
|
||||||
def Err3 : Error<"err3", [{
|
// def Err3 : Error<"err3", [{
|
||||||
err3
|
// err3
|
||||||
multiline
|
// multiline
|
||||||
desc
|
// desc
|
||||||
}]>;
|
// }]>;
|
||||||
|
|
||||||
|
def UnknownError: Error<"Can't find any description for this error.">;
|
||||||
|
|
||||||
|
def DefExpectSymbol: Error<"The first argument to 'def' has to be a Symbol.">;
|
||||||
|
|
||||||
|
def DefWrongNumberOfArgs: Error<"Wrong number of arguments is passed to the 'def' form.">;
|
||||||
|
|
||||||
|
def FnNoArgsList: Error<"'fn' form requires an argument list.">;
|
||||||
|
|
||||||
|
def FnArgsMustBeList: Error<"'fn' arguments should be a list.">;
|
||||||
|
|
||||||
|
def CantResolveSymbol: Error<"Can't resolve the given name.">;
|
||||||
|
|
||||||
|
def DontKnowHowToCallNode: Error<"Don't know how to call the given expression.">;
|
||||||
|
|
||||||
|
def PassFailureError: Error<"Pass Failure.">;
|
||||||
|
|
||||||
|
def NSLoadError: Error<"Faild to find a namespace.">;
|
||||||
|
|
||||||
|
def NSAddToSMError: Error<"Faild to add the namespace to the source manager.">;
|
||||||
|
|
||||||
|
def
|
||||||
|
EOFWhileScaningAList: Error<"EOF reached before closing of list">;
|
||||||
|
|
||||||
|
def InvalidDigitForNumber: Error<"Invalid digit for a number.">;
|
||||||
|
|
||||||
|
def
|
||||||
|
TwoFloatPoints: Error<"Two or more float point characters in a number">;
|
||||||
|
|
||||||
|
def
|
||||||
|
InvalidCharacterForSymbol: Error<"Invalid character for a symbol">;
|
||||||
|
|
||||||
|
def CompilationError: Error<"Compilation error!">;
|
||||||
|
|
||||||
|
defvar errorsIndex = [
|
||||||
|
UnknownError,
|
||||||
|
DefExpectSymbol,
|
||||||
|
DefWrongNumberOfArgs,
|
||||||
|
FnNoArgsList,
|
||||||
|
FnArgsMustBeList,
|
||||||
|
CantResolveSymbol,
|
||||||
|
DontKnowHowToCallNode,
|
||||||
|
PassFailureError,
|
||||||
|
NSLoadError,
|
||||||
|
NSAddToSMError,
|
||||||
|
EOFWhileScaningAList,
|
||||||
|
InvalidDigitForNumber,
|
||||||
|
TwoFloatPoints,
|
||||||
|
InvalidCharacterForSymbol,
|
||||||
|
CompilationError,
|
||||||
|
];
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#define SERENE_EXPRS_CALL_H
|
#define SERENE_EXPRS_CALL_H
|
||||||
|
|
||||||
#include "serene/context.h"
|
#include "serene/context.h"
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/exprs/list.h"
|
#include "serene/exprs/list.h"
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#define SERENE_EXPRS_DEF_H
|
#define SERENE_EXPRS_DEF_H
|
||||||
|
|
||||||
#include "serene/context.h"
|
#include "serene/context.h"
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
|
|
||||||
#include <llvm/ADT/StringRef.h>
|
#include <llvm/ADT/StringRef.h>
|
||||||
|
|
|
@ -20,13 +20,14 @@
|
||||||
#define SERENE_EXPRS_EXPRESSION_H
|
#define SERENE_EXPRS_EXPRESSION_H
|
||||||
|
|
||||||
#include "serene/context.h"
|
#include "serene/context.h"
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/traits.h"
|
#include "serene/exprs/traits.h"
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
#include "serene/reader/location.h"
|
#include "serene/reader/location.h"
|
||||||
#include "serene/semantics.h"
|
#include "serene/semantics.h"
|
||||||
#include "serene/utils.h"
|
#include "serene/utils.h"
|
||||||
|
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
#include <mlir/IR/BuiltinOps.h>
|
#include <mlir/IR/BuiltinOps.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -40,12 +41,12 @@ namespace exprs {
|
||||||
class Expression;
|
class Expression;
|
||||||
|
|
||||||
using Node = std::shared_ptr<Expression>;
|
using Node = std::shared_ptr<Expression>;
|
||||||
using MaybeNode = Result<Node, errors::ErrorTree>;
|
using MaybeNode = llvm::Expected<Node>;
|
||||||
|
|
||||||
using Ast = std::vector<Node>;
|
using Ast = std::vector<Node>;
|
||||||
using MaybeAst = Result<Ast, errors::ErrorTree>;
|
using MaybeAst = llvm::Expected<Ast>;
|
||||||
|
|
||||||
static auto EmptyNode = MaybeNode::success(nullptr);
|
static auto EmptyNode = nullptr;
|
||||||
|
|
||||||
/// The base class of the expressions which provides the common interface for
|
/// The base class of the expressions which provides the common interface for
|
||||||
/// the expressions to implement.
|
/// the expressions to implement.
|
||||||
|
@ -111,34 +112,25 @@ std::shared_ptr<T> makeAndCast(Args &&...args) {
|
||||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The helper function to create a new `Node` and use that as the success case
|
/// The helper function to create a new `Node` and returnsit. It should be useds
|
||||||
// of a `Result`. It should be useds where every we want to return a `MaybeNode`
|
/// where every we want to return a `MaybeNode` successfully.
|
||||||
/// successfully
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
Result<Node, errors::ErrorTree> makeSuccessfulNode(Args &&...args) {
|
MaybeNode makeSuccessfulNode(Args &&...args) {
|
||||||
return Result<Node, errors::ErrorTree>::success(
|
return make<T>(std::forward<Args>(args)...);
|
||||||
make<T>(std::forward<Args>(args)...));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The hlper function to create an Errorful `Result<T,...>` (`T` would be
|
/// The hlper function to creates an Error (`llvm::Error`) by passing all
|
||||||
/// either `Node` or `Ast` most of the time) with just one error created from
|
/// the given arguments to the constructor of the template param `E`.
|
||||||
/// passing any argument to this function to the `serene::errors::Error`
|
template <typename E, typename T = Node, typename... Args>
|
||||||
/// constructor.
|
llvm::Expected<T> makeErrorful(Args &&...args) {
|
||||||
template <typename T, typename... Args>
|
return llvm::make_error<E>(std::forward<Args>(args)...);
|
||||||
Result<T, errors::ErrorTree> makeErrorful(Args &&...args) {
|
|
||||||
std::vector<errors::ErrorPtr> v{
|
|
||||||
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
|
|
||||||
return Result<T, errors::ErrorTree>::error(v);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The hlper function to create an Error node (The failure case of a MaybeNod)
|
/// The hlper function to creates an Error (`llvm::Error`) by passing all
|
||||||
/// with just one error created from passing any argument to this function to
|
/// the given arguments to the constructor of the template param `E`.
|
||||||
/// the `serene::errors::Error` constructor.
|
template <typename E, typename... Args>
|
||||||
template <typename... Args>
|
|
||||||
MaybeNode makeErrorNode(Args &&...args) {
|
MaybeNode makeErrorNode(Args &&...args) {
|
||||||
std::vector<errors::ErrorPtr> v{
|
return makeErrorful<E, Node>(std::forward<Args>(args)...);
|
||||||
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
|
|
||||||
return MaybeNode::error(v);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Convert the given AST to string by calling the `toString` method
|
/// Convert the given AST to string by calling the `toString` method
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#define SERENE_EXPRS_FN_H
|
#define SERENE_EXPRS_FN_H
|
||||||
|
|
||||||
#include "serene/context.h"
|
#include "serene/context.h"
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/exprs/list.h"
|
#include "serene/exprs/list.h"
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#define SERENE_JIT_HALLEY_H
|
#define SERENE_JIT_HALLEY_H
|
||||||
|
|
||||||
#include "serene/errors.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/errors/error.h"
|
|
||||||
#include "serene/export.h"
|
#include "serene/export.h"
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
#include "serene/utils.h"
|
#include "serene/utils.h"
|
||||||
|
@ -58,7 +57,7 @@ namespace jit {
|
||||||
class Halley;
|
class Halley;
|
||||||
|
|
||||||
using MaybeJIT = llvm::Expected<std::unique_ptr<Halley>>;
|
using MaybeJIT = llvm::Expected<std::unique_ptr<Halley>>;
|
||||||
using MaybeJITPtr = serene::Result<void (*)(void **), errors::ErrorTree>;
|
using MaybeJITPtr = llvm::Expected<void (*)(void **)>;
|
||||||
/// A simple object cache following Lang's LLJITWithObjectCache example and
|
/// A simple object cache following Lang's LLJITWithObjectCache example and
|
||||||
/// MLIR's SimpelObjectCache.
|
/// MLIR's SimpelObjectCache.
|
||||||
class ObjectCache : public llvm::ObjectCache {
|
class ObjectCache : public llvm::ObjectCache {
|
||||||
|
@ -179,10 +178,9 @@ public:
|
||||||
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
|
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
|
||||||
symbolMap);
|
symbolMap);
|
||||||
|
|
||||||
llvm::Optional<errors::ErrorTree> addNS(Namespace &ns,
|
llvm::Error addNS(Namespace &ns, reader::LocationRange &loc);
|
||||||
reader::LocationRange &loc);
|
|
||||||
|
|
||||||
llvm::Optional<errors::ErrorTree> addAST(exprs::Ast &ast);
|
llvm::Error addAST(exprs::Ast &ast);
|
||||||
|
|
||||||
Namespace &getActiveNS();
|
Namespace &getActiveNS();
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#define SERENE_NAMESPACE_H
|
#define SERENE_NAMESPACE_H
|
||||||
|
|
||||||
#include "serene/environment.h"
|
#include "serene/environment.h"
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/export.h"
|
#include "serene/export.h"
|
||||||
#include "serene/slir/generatable.h"
|
#include "serene/slir/generatable.h"
|
||||||
#include "serene/traits.h"
|
#include "serene/traits.h"
|
||||||
|
@ -47,6 +47,7 @@
|
||||||
#include <llvm/ExecutionEngine/Orc/Core.h>
|
#include <llvm/ExecutionEngine/Orc/Core.h>
|
||||||
#include <llvm/ExecutionEngine/Orc/ThreadSafeModule.h>
|
#include <llvm/ExecutionEngine/Orc/ThreadSafeModule.h>
|
||||||
#include <llvm/IR/Module.h>
|
#include <llvm/IR/Module.h>
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
#include <mlir/IR/Builders.h>
|
#include <mlir/IR/Builders.h>
|
||||||
#include <mlir/IR/BuiltinOps.h>
|
#include <mlir/IR/BuiltinOps.h>
|
||||||
#include <mlir/IR/OwningOpRef.h>
|
#include <mlir/IR/OwningOpRef.h>
|
||||||
|
@ -72,7 +73,7 @@ using Ast = std::vector<Node>;
|
||||||
} // namespace exprs
|
} // namespace exprs
|
||||||
|
|
||||||
using NSPtr = std::shared_ptr<Namespace>;
|
using NSPtr = std::shared_ptr<Namespace>;
|
||||||
using MaybeNS = Result<NSPtr, errors::ErrorTree>;
|
using MaybeNS = llvm::Expected<NSPtr>;
|
||||||
using MaybeModule = llvm::Optional<llvm::orc::ThreadSafeModule>;
|
using MaybeModule = llvm::Optional<llvm::orc::ThreadSafeModule>;
|
||||||
using MaybeModuleOp = llvm::Optional<mlir::OwningOpRef<mlir::ModuleOp>>;
|
using MaybeModuleOp = llvm::Optional<mlir::OwningOpRef<mlir::ModuleOp>>;
|
||||||
using SemanticEnv = Environment<std::string, exprs::Node>;
|
using SemanticEnv = Environment<std::string, exprs::Node>;
|
||||||
|
@ -137,7 +138,7 @@ public:
|
||||||
/// many elements.
|
/// many elements.
|
||||||
///
|
///
|
||||||
/// This function runs the semantic analyzer on the \p ast as well.
|
/// This function runs the semantic analyzer on the \p ast as well.
|
||||||
errors::OptionalErrors addTree(exprs::Ast &ast);
|
llvm::Error addTree(exprs::Ast &ast);
|
||||||
exprs::Ast &getTree();
|
exprs::Ast &getTree();
|
||||||
|
|
||||||
const std::vector<llvm::StringRef> &getSymList() { return symbolList; };
|
const std::vector<llvm::StringRef> &getSymList() { return symbolList; };
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#define SERENE_SEMANTICS_H
|
#define SERENE_SEMANTICS_H
|
||||||
|
|
||||||
#include "serene/environment.h"
|
#include "serene/environment.h"
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/utils.h"
|
#include "serene/utils.h"
|
||||||
|
|
||||||
#include <llvm/ADT/StringRef.h>
|
#include <llvm/ADT/StringRef.h>
|
||||||
|
@ -39,7 +39,7 @@ class Namespace;
|
||||||
using SemanticEnv = Environment<std::string, exprs::Node>;
|
using SemanticEnv = Environment<std::string, exprs::Node>;
|
||||||
namespace semantics {
|
namespace semantics {
|
||||||
|
|
||||||
using AnalyzeResult = Result<exprs::Ast, std::vector<errors::ErrorPtr>>;
|
using AnalyzeResult = llvm::Expected<exprs::Ast>;
|
||||||
|
|
||||||
/// This struct represent the state necessary for each analysis job.
|
/// This struct represent the state necessary for each analysis job.
|
||||||
struct AnalysisState {
|
struct AnalysisState {
|
||||||
|
@ -62,10 +62,9 @@ std::unique_ptr<AnalysisState> makeAnalysisState(Args &&...args) {
|
||||||
/// The entry point to the Semantic analysis phase. It calls the `analyze`
|
/// The entry point to the Semantic analysis phase. It calls the `analyze`
|
||||||
/// method of each node in the given \p form and creates a new AST that
|
/// method of each node in the given \p form and creates a new AST that
|
||||||
/// contains a more comprehensive set of nodes in a semantically correct
|
/// contains a more comprehensive set of nodes in a semantically correct
|
||||||
/// AST. If the `analyze` method of a node return a `nullptr` value as the
|
/// AST. If the `analyze` method of a node return a `nullptr` value then the
|
||||||
/// `success` result (Checkout the `Result` type in `utils.h`) then the
|
/// original node will be used instead. Any possible error will be returned.
|
||||||
/// original node will be used instead. Any possible error will return as
|
///
|
||||||
/// the `error` case of the `Result` type.
|
|
||||||
/// \param state The semantic analysis state that keep track of the envs.
|
/// \param state The semantic analysis state that keep track of the envs.
|
||||||
/// \param form The actual AST in question.
|
/// \param form The actual AST in question.
|
||||||
AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms);
|
AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms);
|
||||||
|
|
|
@ -50,13 +50,11 @@ add_library(serene
|
||||||
jit/layers.cpp
|
jit/layers.cpp
|
||||||
jit/halley.cpp
|
jit/halley.cpp
|
||||||
|
|
||||||
|
errors.cpp
|
||||||
|
|
||||||
# Reader
|
# Reader
|
||||||
reader/reader.cpp
|
reader/reader.cpp
|
||||||
|
|
||||||
# Errors
|
|
||||||
errors/error.cpp
|
|
||||||
|
|
||||||
# IR
|
# IR
|
||||||
slir/slir.cpp
|
slir/slir.cpp
|
||||||
slir/dialect.cpp
|
slir/dialect.cpp
|
||||||
|
|
|
@ -126,11 +126,11 @@ MaybeNS SereneContext::importNamespace(const std::string &name,
|
||||||
auto maybeNS = readNamespace(name, loc);
|
auto maybeNS = readNamespace(name, loc);
|
||||||
|
|
||||||
if (maybeNS) {
|
if (maybeNS) {
|
||||||
auto &ns = maybeNS.getValue();
|
auto &ns = *maybeNS;
|
||||||
auto err = jit->addNS(*ns, loc);
|
if (auto err = jit->addNS(*ns, loc)) {
|
||||||
if (err) {
|
return err;
|
||||||
return MaybeNS::error(err.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
insertNS(ns);
|
insertNS(ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "serene/utils.h"
|
#include "serene/utils.h"
|
||||||
|
|
||||||
#include <llvm/ADT/StringRef.h>
|
#include <llvm/ADT/StringRef.h>
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
#include <llvm/Support/FormatAdapters.h>
|
#include <llvm/Support/FormatAdapters.h>
|
||||||
#include <llvm/Support/FormatVariadic.h>
|
#include <llvm/Support/FormatVariadic.h>
|
||||||
#include <llvm/Support/WithColor.h>
|
#include <llvm/Support/WithColor.h>
|
||||||
|
@ -158,8 +159,7 @@ void DiagnosticEngine::print(llvm::raw_ostream &os, Diagnostic &d) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Diagnostic DiagnosticEngine::toDiagnostic(reader::LocationRange loc,
|
Diagnostic DiagnosticEngine::toDiagnostic(reader::LocationRange loc,
|
||||||
errors::ErrorVariant &e,
|
llvm::Error &e, llvm::StringRef msg,
|
||||||
llvm::StringRef msg,
|
|
||||||
llvm::StringRef fn) {
|
llvm::StringRef fn) {
|
||||||
|
|
||||||
return Diagnostic(ctx, loc, &e, msg, fn);
|
return Diagnostic(ctx, loc, &e, msg, fn);
|
||||||
|
@ -171,8 +171,7 @@ void DiagnosticEngine::enqueueError(llvm::StringRef msg) {
|
||||||
};
|
};
|
||||||
|
|
||||||
void DiagnosticEngine::emitSyntaxError(reader::LocationRange loc,
|
void DiagnosticEngine::emitSyntaxError(reader::LocationRange loc,
|
||||||
errors::ErrorVariant &e,
|
llvm::Error &e, llvm::StringRef msg) {
|
||||||
llvm::StringRef msg) {
|
|
||||||
Diagnostic diag(ctx, loc, &e, msg);
|
Diagnostic diag(ctx, loc, &e, msg);
|
||||||
|
|
||||||
diag.print(llvm::errs(), "SyntaxError");
|
diag.print(llvm::errs(), "SyntaxError");
|
||||||
|
@ -203,23 +202,27 @@ std::unique_ptr<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx) {
|
||||||
return std::make_unique<DiagnosticEngine>(ctx);
|
return std::make_unique<DiagnosticEngine>(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiagnosticEngine::emit(const errors::ErrorPtr &err) {
|
void DiagnosticEngine::emit(const llvm::Error &err) {
|
||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
// TODO: create a diag and print it
|
// TODO: create a diag and print it
|
||||||
llvm::errs() << err->toString() << "\n";
|
llvm::errs() << err << "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
void DiagnosticEngine::emit(const errors::ErrorTree &errs) {
|
// void DiagnosticEngine::emit(const llvm::Error &errs) {
|
||||||
for (const auto &e : errs) {
|
//
|
||||||
emit(e);
|
// // for (const auto &e : errs) {
|
||||||
}
|
// // emit(e);
|
||||||
};
|
// // }
|
||||||
|
//
|
||||||
|
// };
|
||||||
|
|
||||||
void panic(SereneContext &ctx, llvm::StringRef msg) {
|
void panic(SereneContext &ctx, llvm::StringRef msg) {
|
||||||
ctx.diagEngine->panic(msg);
|
ctx.diagEngine->panic(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
void throwErrors(SereneContext &ctx, errors::ErrorTree &errs) {
|
void throwErrors(SereneContext &ctx, llvm::Error &errs) {
|
||||||
|
// llvm::handleErrors(errs,
|
||||||
|
// [](const errors::SereneError &e){});
|
||||||
ctx.diagEngine->emit(errs);
|
ctx.diagEngine->emit(errs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,22 +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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SERENE_ERRORS_TRAITS_H
|
#include "serene/errors.h"
|
||||||
#define SERENE_ERRORS_TRAITS_H
|
|
||||||
|
|
||||||
#include "serene/errors/constants.h"
|
#define GET_ERRS_ARRAY
|
||||||
#include "serene/traits.h"
|
#include "serene/errors/errs.h.inc"
|
||||||
|
|
||||||
namespace serene::errors {
|
|
||||||
template <typename ConcreteType>
|
|
||||||
class IError : public TraitBase<ConcreteType, IError> {
|
|
||||||
public:
|
|
||||||
IError(){};
|
|
||||||
IError(const IError &) = delete;
|
|
||||||
|
|
||||||
ErrorVariant *getVariant();
|
|
||||||
std::string getMessage();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace serene::errors
|
|
||||||
#endif
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Serene Programming Language
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, version 2.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "serene/errors/error.h"
|
|
||||||
|
|
||||||
#include <llvm/Support/FormatVariadic.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace serene {
|
|
||||||
namespace errors {
|
|
||||||
|
|
||||||
std::string Error::toString() const {
|
|
||||||
return llvm::formatv("<Error E{0}: {1}>", this->variant->id, this->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
reader::LocationRange &Error::where() { return this->location; };
|
|
||||||
|
|
||||||
ErrorVariant *Error::getVariant() { return this->variant; }
|
|
||||||
|
|
||||||
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
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "serene/exprs/call.h"
|
#include "serene/exprs/call.h"
|
||||||
|
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/def.h"
|
#include "serene/exprs/def.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/exprs/list.h"
|
#include "serene/exprs/list.h"
|
||||||
|
@ -63,7 +63,7 @@ MaybeNode Call::make(semantics::AnalysisState &state, List *list) {
|
||||||
return maybeFirst;
|
return maybeFirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node first = maybeFirst.getValue();
|
Node &first = *maybeFirst;
|
||||||
|
|
||||||
// No rewrite is needed for the first element
|
// No rewrite is needed for the first element
|
||||||
if (!first) {
|
if (!first) {
|
||||||
|
@ -97,7 +97,7 @@ MaybeNode Call::make(semantics::AnalysisState &state, List *list) {
|
||||||
if (!maybeResult.hasValue()) {
|
if (!maybeResult.hasValue()) {
|
||||||
std::string msg =
|
std::string msg =
|
||||||
llvm::formatv("Can't resolve the symbol '{0}'", sym->name);
|
llvm::formatv("Can't resolve the symbol '{0}'", sym->name);
|
||||||
return makeErrorful<Node>(sym->location, errors::CantResolveSymbol, msg);
|
return errors::makeError<errors::CantResolveSymbol>(sym->location, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
targetNode = std::move(maybeResult.getValue());
|
targetNode = std::move(maybeResult.getValue());
|
||||||
|
@ -122,7 +122,7 @@ MaybeNode Call::make(semantics::AnalysisState &state, List *list) {
|
||||||
default: {
|
default: {
|
||||||
std::string msg = llvm::formatv("Don't know how to call a '{0}'",
|
std::string msg = llvm::formatv("Don't know how to call a '{0}'",
|
||||||
stringifyExprType(first->getType()));
|
stringifyExprType(first->getType()));
|
||||||
return makeErrorful<Node>(first->location, errors::DontKnowHowToCallNode,
|
return errors::makeError<errors::DontKnowHowToCallNode>(first->location,
|
||||||
msg);
|
msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -130,11 +130,10 @@ MaybeNode Call::make(semantics::AnalysisState &state, List *list) {
|
||||||
auto analyzedParams = semantics::analyze(state, rawParams);
|
auto analyzedParams = semantics::analyze(state, rawParams);
|
||||||
|
|
||||||
if (!analyzedParams) {
|
if (!analyzedParams) {
|
||||||
return MaybeNode::error(analyzedParams.getError());
|
return analyzedParams.takeError();
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeSuccessfulNode<Call>(list->location, targetNode,
|
return makeSuccessfulNode<Call>(list->location, targetNode, *analyzedParams);
|
||||||
analyzedParams.getValue());
|
|
||||||
};
|
};
|
||||||
} // namespace exprs
|
} // namespace exprs
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "serene/exprs/def.h"
|
#include "serene/exprs/def.h"
|
||||||
|
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/exprs/fn.h"
|
#include "serene/exprs/fn.h"
|
||||||
#include "serene/exprs/list.h"
|
#include "serene/exprs/list.h"
|
||||||
|
@ -55,8 +55,8 @@ MaybeNode Def::make(semantics::AnalysisState &state, List *list) {
|
||||||
// TODO: Add support for docstring as the 3rd argument (4th element)
|
// TODO: Add support for docstring as the 3rd argument (4th element)
|
||||||
if (list->count() != 3) {
|
if (list->count() != 3) {
|
||||||
std::string msg = llvm::formatv("Expected 3 got {0}", list->count());
|
std::string msg = llvm::formatv("Expected 3 got {0}", list->count());
|
||||||
return makeErrorful<Node>(list->elements[0]->location,
|
return errors::makeError<errors::DefWrongNumberOfArgs>(
|
||||||
errors::DefWrongNumberOfArgs, msg);
|
list->elements[0]->location, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that the list starts with a `def`
|
// Make sure that the list starts with a `def`
|
||||||
|
@ -68,8 +68,8 @@ MaybeNode Def::make(semantics::AnalysisState &state, List *list) {
|
||||||
// Make sure that the first argument is a Symbol
|
// Make sure that the first argument is a Symbol
|
||||||
Symbol *binding = llvm::dyn_cast<Symbol>(list->elements[1].get());
|
Symbol *binding = llvm::dyn_cast<Symbol>(list->elements[1].get());
|
||||||
if (binding == nullptr) {
|
if (binding == nullptr) {
|
||||||
return makeErrorful<Node>(list->elements[1]->location,
|
return errors::makeError<errors::DefExpectSymbol>(
|
||||||
errors::DefExpectSymbol, "");
|
list->elements[1]->location);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyze the value
|
// Analyze the value
|
||||||
|
@ -79,7 +79,7 @@ MaybeNode Def::make(semantics::AnalysisState &state, List *list) {
|
||||||
// TODO: To refactor this logic into a generic function
|
// TODO: To refactor this logic into a generic function
|
||||||
if (value) {
|
if (value) {
|
||||||
// Success value
|
// Success value
|
||||||
auto &valueNode = value.getValue();
|
auto &valueNode = *value;
|
||||||
|
|
||||||
if (valueNode) {
|
if (valueNode) {
|
||||||
// A rewrite is necessary
|
// A rewrite is necessary
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "serene/exprs/fn.h"
|
#include "serene/exprs/fn.h"
|
||||||
|
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/exprs/list.h"
|
#include "serene/exprs/list.h"
|
||||||
#include "serene/exprs/symbol.h"
|
#include "serene/exprs/symbol.h"
|
||||||
|
@ -66,8 +66,8 @@ MaybeNode Fn::make(semantics::AnalysisState &state, List *list) {
|
||||||
|
|
||||||
// TODO: Add support for docstring as the 3rd argument (4th element)
|
// TODO: Add support for docstring as the 3rd argument (4th element)
|
||||||
if (list->count() < 2) {
|
if (list->count() < 2) {
|
||||||
return makeErrorful<Node>(list->elements[0]->location, errors::FnNoArgsList,
|
return errors::makeError<errors::FnNoArgsList>(
|
||||||
"The argument list is mandatory.");
|
list->elements[0]->location, "The argument list is mandatory.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *fnSym = llvm::dyn_cast<Symbol>(list->elements[0].get());
|
Symbol *fnSym = llvm::dyn_cast<Symbol>(list->elements[0].get());
|
||||||
|
@ -83,8 +83,8 @@ MaybeNode Fn::make(semantics::AnalysisState &state, List *list) {
|
||||||
llvm::formatv("Arguments of a function has to be a list, got '{0}'",
|
llvm::formatv("Arguments of a function has to be a list, got '{0}'",
|
||||||
stringifyExprType(list->elements[1]->getType()));
|
stringifyExprType(list->elements[1]->getType()));
|
||||||
|
|
||||||
return makeErrorful<Node>(list->elements[1]->location,
|
return errors::makeError<errors::FnArgsMustBeList>(
|
||||||
errors::FnArgsMustBeList, msg);
|
list->elements[1]->location, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast body;
|
Ast body;
|
||||||
|
@ -100,10 +100,10 @@ MaybeNode Fn::make(semantics::AnalysisState &state, List *list) {
|
||||||
auto maybeAst = semantics::analyze(state, body);
|
auto maybeAst = semantics::analyze(state, body);
|
||||||
|
|
||||||
if (!maybeAst) {
|
if (!maybeAst) {
|
||||||
return MaybeNode::error(std::move(maybeAst.getError()));
|
return maybeAst.takeError();
|
||||||
}
|
}
|
||||||
|
|
||||||
body = maybeAst.getValue();
|
body = *maybeAst;
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeSuccessfulNode<Fn>(ctx, list->location, *args, body);
|
return makeSuccessfulNode<Fn>(ctx, list->location, *args, body);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "serene/exprs/list.h"
|
#include "serene/exprs/list.h"
|
||||||
|
|
||||||
#include "serene/errors/error.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/call.h"
|
#include "serene/exprs/call.h"
|
||||||
#include "serene/exprs/def.h"
|
#include "serene/exprs/def.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
|
|
|
@ -29,8 +29,7 @@
|
||||||
|
|
||||||
#include "serene/context.h"
|
#include "serene/context.h"
|
||||||
#include "serene/diagnostics.h"
|
#include "serene/diagnostics.h"
|
||||||
#include "serene/errors/constants.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/errors/error.h"
|
|
||||||
#include "serene/exprs/symbol.h"
|
#include "serene/exprs/symbol.h"
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
#include "serene/utils.h"
|
#include "serene/utils.h"
|
||||||
|
@ -202,18 +201,16 @@ MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
|
||||||
auto *ns = ctx.getNS(sym.nsName);
|
auto *ns = ctx.getNS(sym.nsName);
|
||||||
|
|
||||||
if (ns == nullptr) {
|
if (ns == nullptr) {
|
||||||
return MaybeJITPtr::error(errors::makeErrorTree(
|
return errors::makeError<errors::CantResolveSymbol>(
|
||||||
sym.location, errors::CantResolveSymbol,
|
sym.location, "Can't find the namespace in the context: " + sym.nsName);
|
||||||
"Can't find the namespace in the context: " + sym.nsName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *dylib = ctx.getLatestJITDylib(*ns);
|
auto *dylib = ctx.getLatestJITDylib(*ns);
|
||||||
//
|
//
|
||||||
|
|
||||||
if (dylib == nullptr) {
|
if (dylib == nullptr) {
|
||||||
return MaybeJITPtr::error(
|
return errors::makeError<errors::CantResolveSymbol>(
|
||||||
errors::makeErrorTree(sym.location, errors::CantResolveSymbol,
|
sym.location, "Don't know about namespace: " + sym.nsName);
|
||||||
"Don't know about namespace: " + sym.nsName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto expectedSymbol =
|
auto expectedSymbol =
|
||||||
|
@ -230,8 +227,7 @@ MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
|
||||||
llvm::raw_string_ostream os(errorMessage);
|
llvm::raw_string_ostream os(errorMessage);
|
||||||
llvm::handleAllErrors(expectedSymbol.takeError(),
|
llvm::handleAllErrors(expectedSymbol.takeError(),
|
||||||
[&os](llvm::ErrorInfoBase &ei) { ei.log(os); });
|
[&os](llvm::ErrorInfoBase &ei) { ei.log(os); });
|
||||||
return MaybeJITPtr::error(errors::makeErrorTree(
|
return errors::makeError<errors::CantResolveSymbol>(sym.location, os.str());
|
||||||
sym.location, errors::CantResolveSymbol, os.str()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rawFPtr = expectedSymbol->getAddress();
|
auto rawFPtr = expectedSymbol->getAddress();
|
||||||
|
@ -239,8 +235,8 @@ MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
|
||||||
auto fptr = reinterpret_cast<void (*)(void **)>(rawFPtr);
|
auto fptr = reinterpret_cast<void (*)(void **)>(rawFPtr);
|
||||||
|
|
||||||
if (fptr == nullptr) {
|
if (fptr == nullptr) {
|
||||||
return MaybeJITPtr::error(errors::makeErrorTree(
|
return errors::makeError<errors::CantResolveSymbol>(
|
||||||
sym.location, errors::CantResolveSymbol, "Lookup function is null!"));
|
sym.location, "Lookup function is null!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return fptr;
|
return fptr;
|
||||||
|
@ -281,8 +277,7 @@ void Halley::registerSymbols(
|
||||||
mainJitDylib.getExecutionSession(), engine->getDataLayout())))));
|
mainJitDylib.getExecutionSession(), engine->getDataLayout())))));
|
||||||
};
|
};
|
||||||
|
|
||||||
llvm::Optional<errors::ErrorTree> Halley::addNS(Namespace &ns,
|
llvm::Error Halley::addNS(Namespace &ns, reader::LocationRange &loc) {
|
||||||
reader::LocationRange &loc) {
|
|
||||||
|
|
||||||
HALLEY_LOG(llvm::formatv("Creating Dylib {0}#{1}", ns.name,
|
HALLEY_LOG(llvm::formatv("Creating Dylib {0}#{1}", ns.name,
|
||||||
ctx.getNumberOfJITDylibs(ns) + 1));
|
ctx.getNumberOfJITDylibs(ns) + 1));
|
||||||
|
@ -291,8 +286,8 @@ llvm::Optional<errors::ErrorTree> Halley::addNS(Namespace &ns,
|
||||||
llvm::formatv("{0}#{1}", ns.name, ctx.getNumberOfJITDylibs(ns) + 1));
|
llvm::formatv("{0}#{1}", ns.name, ctx.getNumberOfJITDylibs(ns) + 1));
|
||||||
|
|
||||||
if (!newDylib) {
|
if (!newDylib) {
|
||||||
return errors::makeErrorTree(loc, errors::CompilationError,
|
return errors::makeError<errors::CompilationError>(
|
||||||
"Filed to create dylib for " + ns.name);
|
loc, "Filed to create dylib for " + ns.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.pushJITDylib(ns, &(*newDylib));
|
ctx.pushJITDylib(ns, &(*newDylib));
|
||||||
|
@ -301,7 +296,7 @@ llvm::Optional<errors::ErrorTree> Halley::addNS(Namespace &ns,
|
||||||
auto maybeModule = ns.compileToLLVM();
|
auto maybeModule = ns.compileToLLVM();
|
||||||
|
|
||||||
if (!maybeModule.hasValue()) {
|
if (!maybeModule.hasValue()) {
|
||||||
return errors::makeErrorTree(loc, errors::CompilationError);
|
return errors::makeError<errors::CompilationError>(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tsm = std::move(maybeModule.getValue());
|
auto tsm = std::move(maybeModule.getValue());
|
||||||
|
@ -310,7 +305,7 @@ llvm::Optional<errors::ErrorTree> Halley::addNS(Namespace &ns,
|
||||||
// TODO: Make sure that the data layout of the module is the same as the
|
// TODO: Make sure that the data layout of the module is the same as the
|
||||||
// engine
|
// engine
|
||||||
cantFail(engine->addIRModule(*newDylib, std::move(tsm)));
|
cantFail(engine->addIRModule(*newDylib, std::move(tsm)));
|
||||||
return llvm::None;
|
return llvm::Error::success();
|
||||||
};
|
};
|
||||||
|
|
||||||
void Halley::setEngine(std::unique_ptr<llvm::orc::LLJIT> e, bool isLazy) {
|
void Halley::setEngine(std::unique_ptr<llvm::orc::LLJIT> e, bool isLazy) {
|
||||||
|
@ -462,12 +457,11 @@ MaybeJIT Halley::make(SereneContext &serene_ctx,
|
||||||
return MaybeJIT(std::move(jitEngine));
|
return MaybeJIT(std::move(jitEngine));
|
||||||
};
|
};
|
||||||
|
|
||||||
llvm::Optional<errors::ErrorTree> Halley::addAST(exprs::Ast &ast) {
|
llvm::Error Halley::addAST(exprs::Ast &ast) {
|
||||||
auto offset = activeNS->getTree().size();
|
auto offset = activeNS->getTree().size();
|
||||||
auto errs = activeNS->addTree(ast);
|
|
||||||
|
|
||||||
if (errs) {
|
if (auto errs = activeNS->addTree(ast)) {
|
||||||
return errs.getValue();
|
return errs;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto maybeModule = activeNS->compileToLLVMFromOffset(offset);
|
auto maybeModule = activeNS->compileToLLVMFromOffset(offset);
|
||||||
|
@ -479,7 +473,7 @@ llvm::Optional<errors::ErrorTree> Halley::addAST(exprs::Ast &ast) {
|
||||||
// TODO: Make sure that the data layout of the module is the same as the
|
// TODO: Make sure that the data layout of the module is the same as the
|
||||||
// engine
|
// engine
|
||||||
cantFail(engine->addIRModule(*dylib, std::move(tsm)));
|
cantFail(engine->addIRModule(*dylib, std::move(tsm)));
|
||||||
return llvm::None;
|
return llvm::Error::success();
|
||||||
};
|
};
|
||||||
|
|
||||||
Namespace &Halley::getActiveNS() { return *activeNS; };
|
Namespace &Halley::getActiveNS() { return *activeNS; };
|
||||||
|
|
|
@ -127,13 +127,11 @@ llvm::Error NSLayer::add(orc::ResourceTrackerSP &rt, llvm::StringRef nsname,
|
||||||
|
|
||||||
if (!maybeNS) {
|
if (!maybeNS) {
|
||||||
// TODO: Fix this by making Serene errors compatible with llvm::Error
|
// TODO: Fix this by making Serene errors compatible with llvm::Error
|
||||||
auto err = maybeNS.getError();
|
auto err = maybeNS.takeError();
|
||||||
return llvm::make_error<llvm::StringError>(
|
return err;
|
||||||
llvm::Twine(err.front()->getMessage()),
|
|
||||||
std::make_error_code(std::errc::io_error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ns = maybeNS.getValue();
|
auto ns = *maybeNS;
|
||||||
|
|
||||||
LAYER_LOG("Add the materialize unit for: " + nsname);
|
LAYER_LOG("Add the materialize unit for: " + nsname);
|
||||||
return rt->getJITDylib().define(
|
return rt->getJITDylib().define(
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
|
|
||||||
#include "serene/context.h"
|
#include "serene/context.h"
|
||||||
#include "serene/errors/constants.h"
|
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/semantics.h"
|
#include "serene/semantics.h"
|
||||||
|
@ -90,13 +89,13 @@ mlir::LogicalResult Namespace::define(std::string &name, exprs::Node &node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
exprs::Ast &Namespace::getTree() { return this->tree; }
|
exprs::Ast &Namespace::getTree() { return this->tree; }
|
||||||
errors::OptionalErrors Namespace::addTree(exprs::Ast &ast) {
|
llvm::Error Namespace::addTree(exprs::Ast &ast) {
|
||||||
|
|
||||||
// TODO: Remove the parse phase
|
// TODO: Remove the parse phase
|
||||||
if (ctx.getTargetPhase() == CompilationPhase::Parse) {
|
if (ctx.getTargetPhase() == CompilationPhase::Parse) {
|
||||||
// we just want the raw AST
|
// we just want the raw AST
|
||||||
this->tree.insert(this->tree.end(), ast.begin(), ast.end());
|
this->tree.insert(this->tree.end(), ast.begin(), ast.end());
|
||||||
return llvm::None;
|
return llvm::Error::success();
|
||||||
}
|
}
|
||||||
auto &rootEnv = getRootEnv();
|
auto &rootEnv = getRootEnv();
|
||||||
|
|
||||||
|
@ -106,13 +105,13 @@ errors::OptionalErrors Namespace::addTree(exprs::Ast &ast) {
|
||||||
auto maybeForm = semantics::analyze(*state, ast);
|
auto maybeForm = semantics::analyze(*state, ast);
|
||||||
|
|
||||||
if (!maybeForm) {
|
if (!maybeForm) {
|
||||||
return maybeForm.getError();
|
return maybeForm.takeError();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto semanticAst = std::move(maybeForm.getValue());
|
auto semanticAst = std::move(*maybeForm);
|
||||||
this->tree.insert(this->tree.end(), semanticAst.begin(), semanticAst.end());
|
this->tree.insert(this->tree.end(), semanticAst.begin(), semanticAst.end());
|
||||||
|
|
||||||
return llvm::None;
|
return llvm::Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint Namespace::nextFnCounter() { return fn_counter++; };
|
uint Namespace::nextFnCounter() { return fn_counter++; };
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "serene/reader/reader.h"
|
#include "serene/reader/reader.h"
|
||||||
|
|
||||||
#include "serene/errors/constants.h"
|
#include "serene/errors.h"
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/exprs/list.h"
|
#include "serene/exprs/list.h"
|
||||||
#include "serene/exprs/number.h"
|
#include "serene/exprs/number.h"
|
||||||
|
@ -225,7 +225,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
|
||||||
LocationRange loc(getCurrentLocation());
|
LocationRange loc(getCurrentLocation());
|
||||||
|
|
||||||
if (isdigit(*c) == 0) {
|
if (isdigit(*c) == 0) {
|
||||||
return exprs::makeErrorNode(loc, errors::InvalidDigitForNumber);
|
return errors::makeError<errors::InvalidDigitForNumber>(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -236,8 +236,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
|
||||||
if ((isdigit(*c) != 0) || *c == '.') {
|
if ((isdigit(*c) != 0) || *c == '.') {
|
||||||
if (*c == '.' && floatNum) {
|
if (*c == '.' && floatNum) {
|
||||||
loc = LocationRange(getCurrentLocation());
|
loc = LocationRange(getCurrentLocation());
|
||||||
ctx.diagEngine->emitSyntaxError(loc, errors::TwoFloatPoints);
|
return errors::makeError<errors::TwoFloatPoints>(loc);
|
||||||
terminate(ctx, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*c == '.') {
|
if (*c == '.') {
|
||||||
|
@ -253,8 +252,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
|
||||||
if (((std::isalpha(*c) != 0) && !empty) || empty) {
|
if (((std::isalpha(*c) != 0) && !empty) || empty) {
|
||||||
advance();
|
advance();
|
||||||
loc.start = getCurrentLocation();
|
loc.start = getCurrentLocation();
|
||||||
ctx.diagEngine->emitSyntaxError(loc, errors::InvalidDigitForNumber);
|
return errors::makeError<errors::InvalidDigitForNumber>(loc);
|
||||||
terminate(ctx, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loc.end = getCurrentLocation();
|
loc.end = getCurrentLocation();
|
||||||
|
@ -278,7 +276,7 @@ exprs::MaybeNode Reader::readSymbol() {
|
||||||
msg = "An extra ')' is detected.";
|
msg = "An extra ')' is detected.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return exprs::makeErrorNode(loc, errors::InvalidCharacterForSymbol, msg);
|
return errors::makeError<errors::InvalidCharacterForSymbol>(loc, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*c == '-') {
|
if (*c == '-') {
|
||||||
|
@ -338,7 +336,7 @@ exprs::MaybeNode Reader::readList() {
|
||||||
advance(true);
|
advance(true);
|
||||||
advance();
|
advance();
|
||||||
list->location.end = getCurrentLocation();
|
list->location.end = getCurrentLocation();
|
||||||
return exprs::makeErrorNode(list->location, errors::EOFWhileScaningAList);
|
return errors::makeError<errors::EOFWhileScaningAList>(list->location);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*c) {
|
switch (*c) {
|
||||||
|
@ -356,12 +354,12 @@ exprs::MaybeNode Reader::readList() {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
list->append(expr.getValue());
|
list->append(*expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (!list_terminated);
|
} while (!list_terminated);
|
||||||
|
|
||||||
return exprs::MaybeNode::success(list);
|
return list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reads an expression by dispatching to the proper reader function.
|
/// Reads an expression by dispatching to the proper reader function.
|
||||||
|
@ -403,18 +401,18 @@ exprs::MaybeAst Reader::read() {
|
||||||
auto tmp = readExpr();
|
auto tmp = readExpr();
|
||||||
|
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
if (tmp.getValue() == nullptr) {
|
if (*tmp == nullptr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->ast.push_back(move(tmp.getValue()));
|
this->ast.push_back(move(*tmp));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return exprs::MaybeAst::error(tmp.getError());
|
return tmp.takeError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return exprs::MaybeAst::success(std::move(this->ast));
|
return std::move(this->ast);
|
||||||
};
|
};
|
||||||
|
|
||||||
exprs::MaybeAst read(SereneContext &ctx, const llvm::StringRef input,
|
exprs::MaybeAst read(SereneContext &ctx, const llvm::StringRef input,
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
|
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
|
|
||||||
namespace serene::semantics {
|
namespace serene::semantics {
|
||||||
|
|
||||||
std::unique_ptr<AnalysisState> AnalysisState::moveToNewEnv() {
|
std::unique_ptr<AnalysisState> AnalysisState::moveToNewEnv() {
|
||||||
|
@ -30,7 +32,7 @@ std::unique_ptr<AnalysisState> AnalysisState::moveToNewEnv() {
|
||||||
};
|
};
|
||||||
|
|
||||||
AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms) {
|
AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms) {
|
||||||
errors::ErrorTree errors;
|
llvm::Error errors = llvm::Error::success();
|
||||||
exprs::Ast ast;
|
exprs::Ast ast;
|
||||||
|
|
||||||
for (auto &element : forms) {
|
for (auto &element : forms) {
|
||||||
|
@ -38,7 +40,7 @@ AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms) {
|
||||||
|
|
||||||
// Is it a `success` result
|
// Is it a `success` result
|
||||||
if (maybeNode) {
|
if (maybeNode) {
|
||||||
auto &node = maybeNode.getValue();
|
auto &node = *maybeNode;
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
// is there a new node to replace the current node ?
|
// is there a new node to replace the current node ?
|
||||||
|
@ -53,15 +55,17 @@ AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms) {
|
||||||
// `analyze` returned an errorful result. This type of error
|
// `analyze` returned an errorful result. This type of error
|
||||||
// is llvm related and has to be raised later
|
// is llvm related and has to be raised later
|
||||||
// (std::move());
|
// (std::move());
|
||||||
auto errVector = maybeNode.getError();
|
auto err = maybeNode.takeError();
|
||||||
errors.insert(errors.end(), errVector.begin(), errVector.end());
|
errors = llvm::joinErrors(std::move(errors), std::move(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors.empty()) {
|
// If the errors (which is an ErrorList) contains error and is
|
||||||
return AnalyzeResult::success(std::move(ast));
|
// not succssful
|
||||||
|
if (!errors) {
|
||||||
|
return std::move(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AnalyzeResult::error(std::move(errors));
|
return std::move(errors);
|
||||||
};
|
};
|
||||||
}; // namespace serene::semantics
|
}; // namespace serene::semantics
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "serene/serene.h"
|
#include "serene/serene.h"
|
||||||
|
|
||||||
#include "serene/diagnostics.h"
|
#include "serene/diagnostics.h"
|
||||||
#include "serene/errors/constants.h"
|
|
||||||
#include "serene/exprs/expression.h"
|
#include "serene/exprs/expression.h"
|
||||||
|
|
||||||
// TODO: Remove it
|
// TODO: Remove it
|
||||||
|
@ -122,7 +121,7 @@ SERENE_EXPORT exprs::MaybeNode eval(SereneContext &ctx, exprs::Ast &input) {
|
||||||
|
|
||||||
auto errs = ctx.jit->addAST(input);
|
auto errs = ctx.jit->addAST(input);
|
||||||
if (errs) {
|
if (errs) {
|
||||||
return exprs::MaybeNode::error(errs.getValue());
|
return errs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto e = input[0];
|
// auto e = input[0];
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include "serene/source_mgr.h"
|
#include "serene/source_mgr.h"
|
||||||
|
|
||||||
#include "serene/errors/constants.h"
|
|
||||||
#include "serene/namespace.h"
|
#include "serene/namespace.h"
|
||||||
#include "serene/reader/location.h"
|
#include "serene/reader/location.h"
|
||||||
#include "serene/reader/reader.h"
|
#include "serene/reader/reader.h"
|
||||||
|
@ -90,10 +89,8 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
MemBufPtr newBufOrErr(findFileInLoadPath(name, importedFile));
|
MemBufPtr newBufOrErr(findFileInLoadPath(name, importedFile));
|
||||||
|
|
||||||
if (newBufOrErr == nullptr) {
|
if (newBufOrErr == nullptr) {
|
||||||
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name);
|
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name).str();
|
||||||
auto err = errors::makeErrorTree(importLoc, errors::NSLoadError,
|
return errors::makeError<errors::NSLoadError>(importLoc, msg);
|
||||||
llvm::StringRef(msg));
|
|
||||||
return MaybeNS::error(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bufferId = AddNewSourceBuffer(std::move(newBufOrErr), importLoc);
|
auto bufferId = AddNewSourceBuffer(std::move(newBufOrErr), importLoc);
|
||||||
|
@ -101,10 +98,8 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
UNUSED(nsTable.insert_or_assign(name, bufferId));
|
UNUSED(nsTable.insert_or_assign(name, bufferId));
|
||||||
|
|
||||||
if (bufferId == 0) {
|
if (bufferId == 0) {
|
||||||
auto msg = llvm::formatv("Couldn't add namespace '{0}'", name);
|
auto msg = llvm::formatv("Couldn't add namespace '{0}'", name).str();
|
||||||
auto err = errors::makeErrorTree(importLoc, errors::NSAddToSMError,
|
return errors::makeError<errors::NSAddToSMError>(importLoc, msg);
|
||||||
llvm::StringRef(msg));
|
|
||||||
return MaybeNS::error(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we moved the buffer to be added as the source storage we
|
// Since we moved the buffer to be added as the source storage we
|
||||||
|
@ -117,17 +112,16 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
|
||||||
|
|
||||||
if (!maybeAst) {
|
if (!maybeAst) {
|
||||||
SMGR_LOG("Couldn't Read namespace: " + name);
|
SMGR_LOG("Couldn't Read namespace: " + name);
|
||||||
return MaybeNS::error(maybeAst.getError());
|
return maybeAst.takeError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the NS and set the AST
|
// Create the NS and set the AST
|
||||||
auto ns =
|
auto ns =
|
||||||
ctx.makeNamespace(name, llvm::Optional(llvm::StringRef(importedFile)));
|
ctx.makeNamespace(name, llvm::Optional(llvm::StringRef(importedFile)));
|
||||||
|
|
||||||
auto errs = ns->addTree(maybeAst.getValue());
|
if (auto errs = ns->addTree(*maybeAst)) {
|
||||||
if (errs) {
|
|
||||||
SMGR_LOG("Couldn't set the AST for namespace: " + name);
|
SMGR_LOG("Couldn't set the AST for namespace: " + name);
|
||||||
return MaybeNS::error(errs.getValue());
|
return errs;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ns;
|
return ns;
|
||||||
|
|
|
@ -84,20 +84,20 @@ int main(int argc, char *argv[]) {
|
||||||
auto maybeAst = serene::read(*ctx, line);
|
auto maybeAst = serene::read(*ctx, line);
|
||||||
|
|
||||||
if (!maybeAst) {
|
if (!maybeAst) {
|
||||||
serene::throwErrors(*ctx, maybeAst.getError());
|
auto err = maybeAst.takeError();
|
||||||
|
serene::throwErrors(*ctx, err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto x = serene::eval(*ctx, maybeAst.getValue());
|
auto x = serene::eval(*ctx, *maybeAst);
|
||||||
|
|
||||||
if (!x.ok()) {
|
if (!x) {
|
||||||
auto errs = x.getError();
|
auto err = x.takeError();
|
||||||
for (auto &err : errs) {
|
serene::throwErrors(*ctx, err);
|
||||||
llvm::errs() << err->getMessage() << "\n";
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
serene::print(*ctx, maybeAst.getValue(), result);
|
|
||||||
|
serene::print(*ctx, *maybeAst, result);
|
||||||
llvm::outs() << result << "\n";
|
llvm::outs() << result << "\n";
|
||||||
|
|
||||||
// Add text to history
|
// Add text to history
|
||||||
|
|
|
@ -332,11 +332,12 @@ int main(int argc, char *argv[]) {
|
||||||
auto maybeNS = ctx->importNamespace(inputNS, runLoc);
|
auto maybeNS = ctx->importNamespace(inputNS, runLoc);
|
||||||
|
|
||||||
if (!maybeNS) {
|
if (!maybeNS) {
|
||||||
throwErrors(*ctx, maybeNS.getError());
|
auto err = maybeNS.takeError();
|
||||||
|
throwErrors(*ctx, err);
|
||||||
return (int)std::errc::no_such_file_or_directory;
|
return (int)std::errc::no_such_file_or_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ns = maybeNS.getValue();
|
auto ns = *maybeNS;
|
||||||
|
|
||||||
switch (emitAction) {
|
switch (emitAction) {
|
||||||
case Action::DumpAST:
|
case Action::DumpAST:
|
||||||
|
@ -360,7 +361,7 @@ int main(int argc, char *argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tsm = std::move(maybeModule.getValue());
|
auto tsm = std::move(*maybeModule);
|
||||||
tsm.withModuleDo([](auto &m) { m.dump(); });
|
tsm.withModuleDo([](auto &m) { m.dump(); });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <llvm/TableGen/Record.h>
|
#include <llvm/TableGen/Record.h>
|
||||||
|
|
||||||
#define DEBUG_TYPE "errors-backend"
|
#define DEBUG_TYPE "errors-backend"
|
||||||
|
#define INSTANCE_SUFFIX "Instance"
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
|
||||||
|
@ -47,9 +48,10 @@ public:
|
||||||
|
|
||||||
static void inNamespace(llvm::StringRef name, llvm::raw_ostream &os,
|
static void inNamespace(llvm::StringRef name, llvm::raw_ostream &os,
|
||||||
std::function<void(llvm::raw_ostream &)> f) {
|
std::function<void(llvm::raw_ostream &)> f) {
|
||||||
|
|
||||||
os << "namespace " << name << " {\n\n";
|
os << "namespace " << name << " {\n\n";
|
||||||
f(os);
|
f(os);
|
||||||
os << "} // namespace " << name << "\n";
|
os << "}; // namespace " << name << "\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
void ErrorsBackend::createErrorClass(const int id, llvm::Record &defRec,
|
void ErrorsBackend::createErrorClass(const int id, llvm::Record &defRec,
|
||||||
|
@ -58,36 +60,31 @@ void ErrorsBackend::createErrorClass(const int id, llvm::Record &defRec,
|
||||||
|
|
||||||
const auto recName = defRec.getName();
|
const auto recName = defRec.getName();
|
||||||
|
|
||||||
os << "class " << recName << " : public SereneError<" << recName << "> {\n"
|
os << "class " << recName << " : public llvm::ErrorInfo<" << recName << ", "
|
||||||
|
<< "SereneError> {\n"
|
||||||
<< "public:\n"
|
<< "public:\n"
|
||||||
<< " static const int ID = " << id << ";\n";
|
<< " using llvm::ErrorInfo<" << recName << ", "
|
||||||
|
<< "SereneError>::ErrorInfo;\n"
|
||||||
|
<< " constexpr static const int ID = " << id << ";\n};\n\n"
|
||||||
|
<< "static const ErrorVariant " << recName << INSTANCE_SUFFIX
|
||||||
|
<< " = ErrorVariant::make(\n"
|
||||||
|
<< " " << id << ",\n"
|
||||||
|
<< " \"" << recName << "\",\n";
|
||||||
|
|
||||||
for (const auto &val : defRec.getValues()) {
|
auto desc = defRec.getValueAsString("desc");
|
||||||
auto valName = val.getName();
|
|
||||||
|
|
||||||
if (!(valName == "title" || valName == "description")) {
|
if (desc.empty()) {
|
||||||
llvm::PrintWarning("Only 'title' and 'description' are allowed.");
|
llvm::PrintError("'desc' field is empty for " + recName);
|
||||||
llvm::PrintWarning("Record: " + recName);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *stringVal = llvm::dyn_cast<llvm::StringInit>(val.getValue());
|
os << " \"" << desc << "\",\n";
|
||||||
|
|
||||||
if (stringVal == nullptr) {
|
auto help = defRec.getValueAsString("help");
|
||||||
llvm::PrintError("The value of " + valName + " is not string.");
|
|
||||||
llvm::PrintError("Record: " + recName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stringVal->getValue().empty()) {
|
if (!help.empty()) {
|
||||||
llvm::PrintError("The value of " + valName + " is an empty string.");
|
|
||||||
llvm::PrintError("Record: " + recName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
os << " inline static const std::string " << valName << " = ";
|
const llvm::MemoryBufferRef value(help, "help");
|
||||||
|
|
||||||
const llvm::MemoryBufferRef value(stringVal->getValue(), valName);
|
|
||||||
llvm::line_iterator lines(value, false);
|
llvm::line_iterator lines(value, false);
|
||||||
while (!lines.is_at_end()) {
|
while (!lines.is_at_end()) {
|
||||||
if (lines.line_number() != 1) {
|
if (lines.line_number() != 1) {
|
||||||
|
@ -103,25 +100,63 @@ void ErrorsBackend::createErrorClass(const int id, llvm::Record &defRec,
|
||||||
os << '\n';
|
os << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
os << " \"\"";
|
||||||
}
|
}
|
||||||
os << "};\n\n";
|
|
||||||
|
os << ");\n";
|
||||||
|
// os << " " << help << ");\n";
|
||||||
|
// auto *stringVal = llvm::dyn_cast<llvm::StringInit>(val.getValue());
|
||||||
};
|
};
|
||||||
|
|
||||||
void ErrorsBackend::createNSBody(llvm::raw_ostream &os) {
|
void ErrorsBackend::createNSBody(llvm::raw_ostream &os) {
|
||||||
int counter = 1;
|
auto *index = records.getGlobal("errorsIndex");
|
||||||
for (const auto &defPair : records.getDefs()) {
|
|
||||||
llvm::Record &defRec = *defPair.second;
|
|
||||||
|
|
||||||
if (!defRec.isSubClassOf("Error")) {
|
if (index == nullptr) {
|
||||||
|
llvm::PrintError("'errorsIndex' var is missing!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *indexList = llvm::dyn_cast<llvm::ListInit>(index);
|
||||||
|
|
||||||
|
if (indexList == nullptr) {
|
||||||
|
llvm::PrintError("'errorsIndex' has to be a list!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << "#ifdef GET_CLASS_DEFS\n";
|
||||||
|
inNamespace("serene::errors", os, [&](llvm::raw_ostream &os) {
|
||||||
|
for (size_t i = 0; i < indexList->size(); i++) {
|
||||||
|
|
||||||
|
// llvm::Record &defRec = *defPair.second;
|
||||||
|
llvm::Record *defRec = indexList->getElementAsRecord(i);
|
||||||
|
|
||||||
|
if (!defRec->isSubClassOf("Error")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
createErrorClass(counter, defRec, os);
|
createErrorClass(i, *defRec, os);
|
||||||
|
|
||||||
counter++;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
(void)records;
|
os << "#undef GET_CLASS_DEFS\n#endif\n\n";
|
||||||
|
|
||||||
|
os << "#ifdef GET_ERRS_ARRAY\n\n";
|
||||||
|
inNamespace("serene::errors", os, [&](llvm::raw_ostream &os) {
|
||||||
|
os << "static const std::array<int, ErrorVariant *> "
|
||||||
|
"variants{\n";
|
||||||
|
for (size_t i = 0; i < indexList->size(); i++) {
|
||||||
|
|
||||||
|
// llvm::Record &defRec = *defPair.second;
|
||||||
|
llvm::Record *defRec = indexList->getElementAsRecord(i);
|
||||||
|
|
||||||
|
if (!defRec->isSubClassOf("Error")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
os << " &" << defRec->getName() << INSTANCE_SUFFIX << ",\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
os << "\n};\n#undef GET_ERRS_ARRAY\n#endif\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorsBackend::run(llvm::raw_ostream &os) {
|
void ErrorsBackend::run(llvm::raw_ostream &os) {
|
||||||
|
@ -130,9 +165,9 @@ void ErrorsBackend::run(llvm::raw_ostream &os) {
|
||||||
|
|
||||||
os << "#include \"serene/errors/base.h\"\n\n#include "
|
os << "#include \"serene/errors/base.h\"\n\n#include "
|
||||||
"<llvm/Support/Error.h>\n\n";
|
"<llvm/Support/Error.h>\n\n";
|
||||||
|
os << "#ifndef SERENE_ERRORS_ERRORS_H\n#define SERENE_ERRORS_ERRORS_H\n\n";
|
||||||
inNamespace("serene::errors", os,
|
createNSBody(os);
|
||||||
[&](llvm::raw_ostream &os) { createNSBody(os); });
|
os << "#endif\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitErrors(llvm::RecordKeeper &rk, llvm::raw_ostream &os) {
|
void emitErrors(llvm::RecordKeeper &rk, llvm::raw_ostream &os) {
|
||||||
|
|
Loading…
Reference in New Issue