Finish up the errors-backend and migrate serene's errs to llvm:

This commit is contained in:
Sameer Rahmani 2022-02-04 22:47:01 +00:00
parent 95e9edf61e
commit 64ee59fbc8
32 changed files with 353 additions and 398 deletions

View File

@ -227,7 +227,7 @@ public:
// TODO: Fix this by calling to the diag engine
if (err) {
llvm::errs() << err.getValue().back()->getMessage() << "\n";
llvm::errs() << err << "\n";
serene::terminate(*ctx, 1);
return nullptr;
}

View File

@ -19,8 +19,7 @@
#ifndef SERENE_DIAGNOSTICS_H
#define SERENE_DIAGNOSTICS_H
#include "serene/errors/constants.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/reader/location.h"
#include "serene/source_mgr.h"
@ -51,16 +50,15 @@ class Diagnostic {
SereneContext &ctx;
reader::LocationRange loc;
std::string fn;
errors::ErrorVariant *err = nullptr;
Type type = Type::Error;
llvm::Error *err = nullptr;
Type type = Type::Error;
std::string message, lineContents;
std::string getPrefix(llvm::StringRef prefix = "");
public:
Diagnostic(SereneContext &ctx, reader::LocationRange loc,
errors::ErrorVariant *e, llvm::StringRef msg,
llvm::StringRef fn = "")
Diagnostic(SereneContext &ctx, reader::LocationRange loc, llvm::Error *e,
llvm::StringRef msg, llvm::StringRef fn = "")
: ctx(ctx), loc(loc), fn(fn), err(e), message(msg){};
protected:
@ -73,7 +71,7 @@ class DiagnosticEngine {
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 = "");
void print(llvm::raw_ostream &os, Diagnostic &d);
@ -82,11 +80,10 @@ public:
DiagnosticEngine(SereneContext &ctx);
void enqueueError(llvm::StringRef msg);
void emitSyntaxError(reader::LocationRange loc, errors::ErrorVariant &e,
void emitSyntaxError(reader::LocationRange loc, llvm::Error &e,
llvm::StringRef msg = "");
void emit(const errors::ErrorPtr &err);
void emit(const errors::ErrorTree &errs);
void emit(const llvm::Error &err);
/// Throw out an error with the given `msg` and terminate the execution
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.
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);
/// Throw the give `llvm::Error` \p errs to the stderr.
SERENE_EXPORT void throwErrors(SereneContext &ctx, llvm::Error &errs);
} // namespace serene
#endif

View File

@ -19,7 +19,21 @@
#ifndef SERENE_ERRORS_H
#define SERENE_ERRORS_H
#include "serene/errors/base.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

View File

@ -24,37 +24,62 @@
#include <system_error>
#include <llvm/Support/Error.h>
#include <llvm/Support/FormatVariadic.h>
namespace serene::errors {
template <typename T>
class SereneError : public llvm::ErrorInfo<T> {
struct ErrorVariant {
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;
std::string msg;
public:
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 &getTitle() const { return T::title; };
std::string &getDesc() const { return T::description; };
std::error_code convertToErrorCode() const { return std::error_code(); };
std::error_code convertToErrorCode() const override {
return std::error_code();
};
SereneError(reader::LocationRange &loc, std::string &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; };
static const void *classID() { return &T::ID; }
static const void *classID() { return &ID; }
bool isA(const void *const id) const override {
// the check with -1 is a shortcut for us to figure
// out whether we're dealing with an Serene error or
// LLVM error
return *(const int *)id == -1 || id == classID() ||
llvm::ErrorInfoBase::isA(id);
return id == classID() || llvm::ErrorInfoBase::isA(id);
}
~SereneError() = default;
};
}; // namespace serene::errors

View File

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

View File

@ -1,23 +1,76 @@
class Error<string _title = "", string _desc = ""> {
string title = _title;
string description = _desc;
class Error<string _desc = "", string _help = ""> {
string desc = _desc;
string help = _help;
}
def Err : Error<"Err1 titel"> {
let description = [{
err1
multiline
desc}];
}
// Examples of how to define a new error
// def Err : Error<"Err1 titel"> {
// let description = [{
// err1
// multiline
// desc}];
// }
def Err2 : Error {
let title = "err 2 titel";
let description = "err2 desc";
}
// def Err2 : Error {
// let title = "err 2 titel";
// let description = "err2 desc";
// }
def Err3 : Error<"err3", [{
err3
multiline
desc
}]>;
// def Err3 : Error<"err3", [{
// err3
// multiline
// 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,
];

View File

@ -20,7 +20,7 @@
#define SERENE_EXPRS_CALL_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"

View File

@ -20,7 +20,7 @@
#define SERENE_EXPRS_DEF_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/expression.h"
#include <llvm/ADT/StringRef.h>

View File

@ -20,13 +20,14 @@
#define SERENE_EXPRS_EXPRESSION_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/traits.h"
#include "serene/namespace.h"
#include "serene/reader/location.h"
#include "serene/semantics.h"
#include "serene/utils.h"
#include <llvm/Support/Error.h>
#include <mlir/IR/BuiltinOps.h>
#include <memory>
@ -40,12 +41,12 @@ namespace exprs {
class Expression;
using Node = std::shared_ptr<Expression>;
using MaybeNode = Result<Node, errors::ErrorTree>;
using MaybeNode = llvm::Expected<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 expressions to implement.
@ -111,34 +112,25 @@ std::shared_ptr<T> makeAndCast(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
// of a `Result`. It should be useds where every we want to return a `MaybeNode`
/// successfully
/// The helper function to create a new `Node` and returnsit. It should be useds
/// where every we want to return a `MaybeNode` successfully.
template <typename T, typename... Args>
Result<Node, errors::ErrorTree> makeSuccessfulNode(Args &&...args) {
return Result<Node, errors::ErrorTree>::success(
make<T>(std::forward<Args>(args)...));
MaybeNode makeSuccessfulNode(Args &&...args) {
return make<T>(std::forward<Args>(args)...);
};
/// The hlper function to create an Errorful `Result<T,...>` (`T` would be
/// either `Node` or `Ast` most of the time) with just one error created from
/// passing any argument to this function to the `serene::errors::Error`
/// constructor.
template <typename T, typename... 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 creates an Error (`llvm::Error`) by passing all
/// the given arguments to the constructor of the template param `E`.
template <typename E, typename T = Node, typename... Args>
llvm::Expected<T> makeErrorful(Args &&...args) {
return llvm::make_error<E>(std::forward<Args>(args)...);
};
/// The hlper function to create an Error node (The failure case of a MaybeNod)
/// with just one error created from passing any argument to this function to
/// the `serene::errors::Error` constructor.
template <typename... Args>
/// The hlper function to creates an Error (`llvm::Error`) by passing all
/// the given arguments to the constructor of the template param `E`.
template <typename E, typename... Args>
MaybeNode makeErrorNode(Args &&...args) {
std::vector<errors::ErrorPtr> v{
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
return MaybeNode::error(v);
return makeErrorful<E, Node>(std::forward<Args>(args)...);
};
/// Convert the given AST to string by calling the `toString` method

View File

@ -20,7 +20,7 @@
#define SERENE_EXPRS_FN_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
#include "serene/namespace.h"

View File

@ -25,7 +25,6 @@
#define SERENE_JIT_HALLEY_H
#include "serene/errors.h"
#include "serene/errors/error.h"
#include "serene/export.h"
#include "serene/namespace.h"
#include "serene/utils.h"
@ -58,7 +57,7 @@ namespace jit {
class 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
/// MLIR's SimpelObjectCache.
class ObjectCache : public llvm::ObjectCache {
@ -179,10 +178,9 @@ public:
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
symbolMap);
llvm::Optional<errors::ErrorTree> addNS(Namespace &ns,
reader::LocationRange &loc);
llvm::Error addNS(Namespace &ns, reader::LocationRange &loc);
llvm::Optional<errors::ErrorTree> addAST(exprs::Ast &ast);
llvm::Error addAST(exprs::Ast &ast);
Namespace &getActiveNS();
};

View File

@ -34,7 +34,7 @@
#define SERENE_NAMESPACE_H
#include "serene/environment.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/export.h"
#include "serene/slir/generatable.h"
#include "serene/traits.h"
@ -47,6 +47,7 @@
#include <llvm/ExecutionEngine/Orc/Core.h>
#include <llvm/ExecutionEngine/Orc/ThreadSafeModule.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/Error.h>
#include <mlir/IR/Builders.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/OwningOpRef.h>
@ -72,7 +73,7 @@ using Ast = std::vector<Node>;
} // namespace exprs
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 MaybeModuleOp = llvm::Optional<mlir::OwningOpRef<mlir::ModuleOp>>;
using SemanticEnv = Environment<std::string, exprs::Node>;
@ -137,7 +138,7 @@ public:
/// many elements.
///
/// 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();
const std::vector<llvm::StringRef> &getSymList() { return symbolList; };

View File

@ -20,7 +20,7 @@
#define SERENE_SEMANTICS_H
#include "serene/environment.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/utils.h"
#include <llvm/ADT/StringRef.h>
@ -39,7 +39,7 @@ class Namespace;
using SemanticEnv = Environment<std::string, exprs::Node>;
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.
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`
/// 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
/// AST. If the `analyze` method of a node return a `nullptr` value as the
/// `success` result (Checkout the `Result` type in `utils.h`) then the
/// original node will be used instead. Any possible error will return as
/// the `error` case of the `Result` type.
/// AST. If the `analyze` method of a node return a `nullptr` value then the
/// original node will be used instead. Any possible error will be returned.
///
/// \param state The semantic analysis state that keep track of the envs.
/// \param form The actual AST in question.
AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms);

View File

@ -50,13 +50,11 @@ add_library(serene
jit/layers.cpp
jit/halley.cpp
errors.cpp
# Reader
reader/reader.cpp
# Errors
errors/error.cpp
# IR
slir/slir.cpp
slir/dialect.cpp

View File

@ -126,11 +126,11 @@ MaybeNS SereneContext::importNamespace(const std::string &name,
auto maybeNS = readNamespace(name, loc);
if (maybeNS) {
auto &ns = maybeNS.getValue();
auto err = jit->addNS(*ns, loc);
if (err) {
return MaybeNS::error(err.getValue());
auto &ns = *maybeNS;
if (auto err = jit->addNS(*ns, loc)) {
return err;
}
insertNS(ns);
}

View File

@ -24,6 +24,7 @@
#include "serene/utils.h"
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/Error.h>
#include <llvm/Support/FormatAdapters.h>
#include <llvm/Support/FormatVariadic.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,
errors::ErrorVariant &e,
llvm::StringRef msg,
llvm::Error &e, llvm::StringRef msg,
llvm::StringRef fn) {
return Diagnostic(ctx, loc, &e, msg, fn);
@ -171,8 +171,7 @@ void DiagnosticEngine::enqueueError(llvm::StringRef msg) {
};
void DiagnosticEngine::emitSyntaxError(reader::LocationRange loc,
errors::ErrorVariant &e,
llvm::StringRef msg) {
llvm::Error &e, llvm::StringRef msg) {
Diagnostic diag(ctx, loc, &e, msg);
diag.print(llvm::errs(), "SyntaxError");
@ -203,23 +202,27 @@ std::unique_ptr<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx) {
return std::make_unique<DiagnosticEngine>(ctx);
}
void DiagnosticEngine::emit(const errors::ErrorPtr &err) {
void DiagnosticEngine::emit(const llvm::Error &err) {
UNUSED(ctx);
// TODO: create a diag and print it
llvm::errs() << err->toString() << "\n";
llvm::errs() << err << "\n";
};
void DiagnosticEngine::emit(const errors::ErrorTree &errs) {
for (const auto &e : errs) {
emit(e);
}
};
// void DiagnosticEngine::emit(const llvm::Error &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) {
void throwErrors(SereneContext &ctx, llvm::Error &errs) {
// llvm::handleErrors(errs,
// [](const errors::SereneError &e){});
ctx.diagEngine->emit(errs);
};

View File

@ -16,22 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERENE_ERRORS_TRAITS_H
#define SERENE_ERRORS_TRAITS_H
#include "serene/errors.h"
#include "serene/errors/constants.h"
#include "serene/traits.h"
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
#define GET_ERRS_ARRAY
#include "serene/errors/errs.h.inc"

View File

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

View File

@ -18,7 +18,7 @@
#include "serene/exprs/call.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/def.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
@ -63,7 +63,7 @@ MaybeNode Call::make(semantics::AnalysisState &state, List *list) {
return maybeFirst;
}
Node first = maybeFirst.getValue();
Node &first = *maybeFirst;
// No rewrite is needed for the first element
if (!first) {
@ -97,7 +97,7 @@ MaybeNode Call::make(semantics::AnalysisState &state, List *list) {
if (!maybeResult.hasValue()) {
std::string msg =
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());
@ -122,19 +122,18 @@ MaybeNode Call::make(semantics::AnalysisState &state, List *list) {
default: {
std::string msg = llvm::formatv("Don't know how to call a '{0}'",
stringifyExprType(first->getType()));
return makeErrorful<Node>(first->location, errors::DontKnowHowToCallNode,
msg);
return errors::makeError<errors::DontKnowHowToCallNode>(first->location,
msg);
}
};
auto analyzedParams = semantics::analyze(state, rawParams);
if (!analyzedParams) {
return MaybeNode::error(analyzedParams.getError());
return analyzedParams.takeError();
}
return makeSuccessfulNode<Call>(list->location, targetNode,
analyzedParams.getValue());
return makeSuccessfulNode<Call>(list->location, targetNode, *analyzedParams);
};
} // namespace exprs
} // namespace serene

View File

@ -18,7 +18,7 @@
#include "serene/exprs/def.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/fn.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)
if (list->count() != 3) {
std::string msg = llvm::formatv("Expected 3 got {0}", list->count());
return makeErrorful<Node>(list->elements[0]->location,
errors::DefWrongNumberOfArgs, msg);
return errors::makeError<errors::DefWrongNumberOfArgs>(
list->elements[0]->location, msg);
}
// 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
Symbol *binding = llvm::dyn_cast<Symbol>(list->elements[1].get());
if (binding == nullptr) {
return makeErrorful<Node>(list->elements[1]->location,
errors::DefExpectSymbol, "");
return errors::makeError<errors::DefExpectSymbol>(
list->elements[1]->location);
}
// Analyze the value
@ -79,7 +79,7 @@ MaybeNode Def::make(semantics::AnalysisState &state, List *list) {
// TODO: To refactor this logic into a generic function
if (value) {
// Success value
auto &valueNode = value.getValue();
auto &valueNode = *value;
if (valueNode) {
// A rewrite is necessary

View File

@ -18,7 +18,7 @@
#include "serene/exprs/fn.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.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)
if (list->count() < 2) {
return makeErrorful<Node>(list->elements[0]->location, errors::FnNoArgsList,
"The argument list is mandatory.");
return errors::makeError<errors::FnNoArgsList>(
list->elements[0]->location, "The argument list is mandatory.");
}
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}'",
stringifyExprType(list->elements[1]->getType()));
return makeErrorful<Node>(list->elements[1]->location,
errors::FnArgsMustBeList, msg);
return errors::makeError<errors::FnArgsMustBeList>(
list->elements[1]->location, msg);
}
Ast body;
@ -100,10 +100,10 @@ MaybeNode Fn::make(semantics::AnalysisState &state, List *list) {
auto maybeAst = semantics::analyze(state, body);
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);

View File

@ -18,7 +18,7 @@
#include "serene/exprs/list.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/call.h"
#include "serene/exprs/def.h"
#include "serene/exprs/expression.h"

View File

@ -29,8 +29,7 @@
#include "serene/context.h"
#include "serene/diagnostics.h"
#include "serene/errors/constants.h"
#include "serene/errors/error.h"
#include "serene/errors.h"
#include "serene/exprs/symbol.h"
#include "serene/namespace.h"
#include "serene/utils.h"
@ -202,18 +201,16 @@ MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
auto *ns = ctx.getNS(sym.nsName);
if (ns == nullptr) {
return MaybeJITPtr::error(errors::makeErrorTree(
sym.location, errors::CantResolveSymbol,
"Can't find the namespace in the context: " + sym.nsName));
return errors::makeError<errors::CantResolveSymbol>(
sym.location, "Can't find the namespace in the context: " + sym.nsName);
}
auto *dylib = ctx.getLatestJITDylib(*ns);
//
if (dylib == nullptr) {
return MaybeJITPtr::error(
errors::makeErrorTree(sym.location, errors::CantResolveSymbol,
"Don't know about namespace: " + sym.nsName));
return errors::makeError<errors::CantResolveSymbol>(
sym.location, "Don't know about namespace: " + sym.nsName);
}
auto expectedSymbol =
@ -230,8 +227,7 @@ MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
llvm::raw_string_ostream os(errorMessage);
llvm::handleAllErrors(expectedSymbol.takeError(),
[&os](llvm::ErrorInfoBase &ei) { ei.log(os); });
return MaybeJITPtr::error(errors::makeErrorTree(
sym.location, errors::CantResolveSymbol, os.str()));
return errors::makeError<errors::CantResolveSymbol>(sym.location, os.str());
}
auto rawFPtr = expectedSymbol->getAddress();
@ -239,8 +235,8 @@ MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
auto fptr = reinterpret_cast<void (*)(void **)>(rawFPtr);
if (fptr == nullptr) {
return MaybeJITPtr::error(errors::makeErrorTree(
sym.location, errors::CantResolveSymbol, "Lookup function is null!"));
return errors::makeError<errors::CantResolveSymbol>(
sym.location, "Lookup function is null!");
}
return fptr;
@ -281,8 +277,7 @@ void Halley::registerSymbols(
mainJitDylib.getExecutionSession(), engine->getDataLayout())))));
};
llvm::Optional<errors::ErrorTree> Halley::addNS(Namespace &ns,
reader::LocationRange &loc) {
llvm::Error Halley::addNS(Namespace &ns, reader::LocationRange &loc) {
HALLEY_LOG(llvm::formatv("Creating Dylib {0}#{1}", ns.name,
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));
if (!newDylib) {
return errors::makeErrorTree(loc, errors::CompilationError,
"Filed to create dylib for " + ns.name);
return errors::makeError<errors::CompilationError>(
loc, "Filed to create dylib for " + ns.name);
}
ctx.pushJITDylib(ns, &(*newDylib));
@ -301,7 +296,7 @@ llvm::Optional<errors::ErrorTree> Halley::addNS(Namespace &ns,
auto maybeModule = ns.compileToLLVM();
if (!maybeModule.hasValue()) {
return errors::makeErrorTree(loc, errors::CompilationError);
return errors::makeError<errors::CompilationError>(loc);
}
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
// engine
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) {
@ -462,12 +457,11 @@ MaybeJIT Halley::make(SereneContext &serene_ctx,
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 errs = activeNS->addTree(ast);
if (errs) {
return errs.getValue();
if (auto errs = activeNS->addTree(ast)) {
return errs;
}
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
// engine
cantFail(engine->addIRModule(*dylib, std::move(tsm)));
return llvm::None;
return llvm::Error::success();
};
Namespace &Halley::getActiveNS() { return *activeNS; };

View File

@ -127,13 +127,11 @@ llvm::Error NSLayer::add(orc::ResourceTrackerSP &rt, llvm::StringRef nsname,
if (!maybeNS) {
// TODO: Fix this by making Serene errors compatible with llvm::Error
auto err = maybeNS.getError();
return llvm::make_error<llvm::StringError>(
llvm::Twine(err.front()->getMessage()),
std::make_error_code(std::errc::io_error));
auto err = maybeNS.takeError();
return err;
}
auto ns = maybeNS.getValue();
auto ns = *maybeNS;
LAYER_LOG("Add the materialize unit for: " + nsname);
return rt->getJITDylib().define(

View File

@ -25,7 +25,6 @@
#include "serene/namespace.h"
#include "serene/context.h"
#include "serene/errors/constants.h"
#include "serene/exprs/expression.h"
#include "serene/llvm/IR/Value.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; }
errors::OptionalErrors Namespace::addTree(exprs::Ast &ast) {
llvm::Error Namespace::addTree(exprs::Ast &ast) {
// TODO: Remove the parse phase
if (ctx.getTargetPhase() == CompilationPhase::Parse) {
// we just want the raw AST
this->tree.insert(this->tree.end(), ast.begin(), ast.end());
return llvm::None;
return llvm::Error::success();
}
auto &rootEnv = getRootEnv();
@ -106,13 +105,13 @@ errors::OptionalErrors Namespace::addTree(exprs::Ast &ast) {
auto maybeForm = semantics::analyze(*state, ast);
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());
return llvm::None;
return llvm::Error::success();
}
uint Namespace::nextFnCounter() { return fn_counter++; };

View File

@ -18,7 +18,7 @@
#include "serene/reader/reader.h"
#include "serene/errors/constants.h"
#include "serene/errors.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
#include "serene/exprs/number.h"
@ -225,7 +225,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
LocationRange loc(getCurrentLocation());
if (isdigit(*c) == 0) {
return exprs::makeErrorNode(loc, errors::InvalidDigitForNumber);
return errors::makeError<errors::InvalidDigitForNumber>(loc);
}
for (;;) {
@ -236,8 +236,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
if ((isdigit(*c) != 0) || *c == '.') {
if (*c == '.' && floatNum) {
loc = LocationRange(getCurrentLocation());
ctx.diagEngine->emitSyntaxError(loc, errors::TwoFloatPoints);
terminate(ctx, 1);
return errors::makeError<errors::TwoFloatPoints>(loc);
}
if (*c == '.') {
@ -253,8 +252,7 @@ exprs::MaybeNode Reader::readNumber(bool neg) {
if (((std::isalpha(*c) != 0) && !empty) || empty) {
advance();
loc.start = getCurrentLocation();
ctx.diagEngine->emitSyntaxError(loc, errors::InvalidDigitForNumber);
terminate(ctx, 1);
return errors::makeError<errors::InvalidDigitForNumber>(loc);
}
loc.end = getCurrentLocation();
@ -278,7 +276,7 @@ exprs::MaybeNode Reader::readSymbol() {
msg = "An extra ')' is detected.";
}
return exprs::makeErrorNode(loc, errors::InvalidCharacterForSymbol, msg);
return errors::makeError<errors::InvalidCharacterForSymbol>(loc, msg);
}
if (*c == '-') {
@ -338,7 +336,7 @@ exprs::MaybeNode Reader::readList() {
advance(true);
advance();
list->location.end = getCurrentLocation();
return exprs::makeErrorNode(list->location, errors::EOFWhileScaningAList);
return errors::makeError<errors::EOFWhileScaningAList>(list->location);
}
switch (*c) {
@ -356,12 +354,12 @@ exprs::MaybeNode Reader::readList() {
return expr;
}
list->append(expr.getValue());
list->append(*expr);
}
} while (!list_terminated);
return exprs::MaybeNode::success(list);
return list;
};
/// Reads an expression by dispatching to the proper reader function.
@ -403,18 +401,18 @@ exprs::MaybeAst Reader::read() {
auto tmp = readExpr();
if (tmp) {
if (tmp.getValue() == nullptr) {
if (*tmp == nullptr) {
break;
}
this->ast.push_back(move(tmp.getValue()));
this->ast.push_back(move(*tmp));
} 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,

View File

@ -22,6 +22,8 @@
#include "serene/exprs/expression.h"
#include "serene/namespace.h"
#include <llvm/Support/Error.h>
namespace serene::semantics {
std::unique_ptr<AnalysisState> AnalysisState::moveToNewEnv() {
@ -30,7 +32,7 @@ std::unique_ptr<AnalysisState> AnalysisState::moveToNewEnv() {
};
AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms) {
errors::ErrorTree errors;
llvm::Error errors = llvm::Error::success();
exprs::Ast ast;
for (auto &element : forms) {
@ -38,7 +40,7 @@ AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms) {
// Is it a `success` result
if (maybeNode) {
auto &node = maybeNode.getValue();
auto &node = *maybeNode;
if (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
// is llvm related and has to be raised later
// (std::move());
auto errVector = maybeNode.getError();
errors.insert(errors.end(), errVector.begin(), errVector.end());
auto err = maybeNode.takeError();
errors = llvm::joinErrors(std::move(errors), std::move(err));
}
}
if (errors.empty()) {
return AnalyzeResult::success(std::move(ast));
// If the errors (which is an ErrorList) contains error and is
// not succssful
if (!errors) {
return std::move(ast);
}
return AnalyzeResult::error(std::move(errors));
return std::move(errors);
};
}; // namespace serene::semantics

View File

@ -25,7 +25,6 @@
#include "serene/serene.h"
#include "serene/diagnostics.h"
#include "serene/errors/constants.h"
#include "serene/exprs/expression.h"
// TODO: Remove it
@ -122,7 +121,7 @@ SERENE_EXPORT exprs::MaybeNode eval(SereneContext &ctx, exprs::Ast &input) {
auto errs = ctx.jit->addAST(input);
if (errs) {
return exprs::MaybeNode::error(errs.getValue());
return errs;
}
// auto e = input[0];

View File

@ -24,7 +24,6 @@
#include "serene/source_mgr.h"
#include "serene/errors/constants.h"
#include "serene/namespace.h"
#include "serene/reader/location.h"
#include "serene/reader/reader.h"
@ -90,10 +89,8 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
MemBufPtr newBufOrErr(findFileInLoadPath(name, importedFile));
if (newBufOrErr == nullptr) {
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name);
auto err = errors::makeErrorTree(importLoc, errors::NSLoadError,
llvm::StringRef(msg));
return MaybeNS::error(err);
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name).str();
return errors::makeError<errors::NSLoadError>(importLoc, msg);
}
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));
if (bufferId == 0) {
auto msg = llvm::formatv("Couldn't add namespace '{0}'", name);
auto err = errors::makeErrorTree(importLoc, errors::NSAddToSMError,
llvm::StringRef(msg));
return MaybeNS::error(err);
auto msg = llvm::formatv("Couldn't add namespace '{0}'", name).str();
return errors::makeError<errors::NSAddToSMError>(importLoc, msg);
}
// 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) {
SMGR_LOG("Couldn't Read namespace: " + name);
return MaybeNS::error(maybeAst.getError());
return maybeAst.takeError();
}
// Create the NS and set the AST
auto ns =
ctx.makeNamespace(name, llvm::Optional(llvm::StringRef(importedFile)));
auto errs = ns->addTree(maybeAst.getValue());
if (errs) {
if (auto errs = ns->addTree(*maybeAst)) {
SMGR_LOG("Couldn't set the AST for namespace: " + name);
return MaybeNS::error(errs.getValue());
return errs;
}
return ns;

View File

@ -84,20 +84,20 @@ int main(int argc, char *argv[]) {
auto maybeAst = serene::read(*ctx, line);
if (!maybeAst) {
serene::throwErrors(*ctx, maybeAst.getError());
auto err = maybeAst.takeError();
serene::throwErrors(*ctx, err);
continue;
}
auto x = serene::eval(*ctx, maybeAst.getValue());
auto x = serene::eval(*ctx, *maybeAst);
if (!x.ok()) {
auto errs = x.getError();
for (auto &err : errs) {
llvm::errs() << err->getMessage() << "\n";
}
if (!x) {
auto err = x.takeError();
serene::throwErrors(*ctx, err);
continue;
}
serene::print(*ctx, maybeAst.getValue(), result);
serene::print(*ctx, *maybeAst, result);
llvm::outs() << result << "\n";
// Add text to history

View File

@ -332,11 +332,12 @@ int main(int argc, char *argv[]) {
auto maybeNS = ctx->importNamespace(inputNS, runLoc);
if (!maybeNS) {
throwErrors(*ctx, maybeNS.getError());
auto err = maybeNS.takeError();
throwErrors(*ctx, err);
return (int)std::errc::no_such_file_or_directory;
}
auto ns = maybeNS.getValue();
auto ns = *maybeNS;
switch (emitAction) {
case Action::DumpAST:
@ -360,7 +361,7 @@ int main(int argc, char *argv[]) {
return 1;
}
auto tsm = std::move(maybeModule.getValue());
auto tsm = std::move(*maybeModule);
tsm.withModuleDo([](auto &m) { m.dump(); });
break;

View File

@ -26,7 +26,8 @@
#include <llvm/TableGen/Error.h>
#include <llvm/TableGen/Record.h>
#define DEBUG_TYPE "errors-backend"
#define DEBUG_TYPE "errors-backend"
#define INSTANCE_SUFFIX "Instance"
namespace serene {
@ -47,9 +48,10 @@ public:
static void inNamespace(llvm::StringRef name, llvm::raw_ostream &os,
std::function<void(llvm::raw_ostream &)> f) {
os << "namespace " << name << " {\n\n";
f(os);
os << "} // namespace " << name << "\n";
os << "}; // namespace " << name << "\n";
};
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();
os << "class " << recName << " : public SereneError<" << recName << "> {\n"
os << "class " << recName << " : public llvm::ErrorInfo<" << recName << ", "
<< "SereneError> {\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 valName = val.getName();
auto desc = defRec.getValueAsString("desc");
if (!(valName == "title" || valName == "description")) {
llvm::PrintWarning("Only 'title' and 'description' are allowed.");
llvm::PrintWarning("Record: " + recName);
continue;
}
if (desc.empty()) {
llvm::PrintError("'desc' field is empty for " + recName);
}
auto *stringVal = llvm::dyn_cast<llvm::StringInit>(val.getValue());
os << " \"" << desc << "\",\n";
if (stringVal == nullptr) {
llvm::PrintError("The value of " + valName + " is not string.");
llvm::PrintError("Record: " + recName);
continue;
}
auto help = defRec.getValueAsString("help");
if (stringVal->getValue().empty()) {
llvm::PrintError("The value of " + valName + " is an empty string.");
llvm::PrintError("Record: " + recName);
continue;
}
if (!help.empty()) {
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);
while (!lines.is_at_end()) {
if (lines.line_number() != 1) {
@ -103,25 +100,63 @@ void ErrorsBackend::createErrorClass(const int id, llvm::Record &defRec,
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) {
int counter = 1;
for (const auto &defPair : records.getDefs()) {
llvm::Record &defRec = *defPair.second;
auto *index = records.getGlobal("errorsIndex");
if (!defRec.isSubClassOf("Error")) {
continue;
}
createErrorClass(counter, defRec, os);
counter++;
if (index == nullptr) {
llvm::PrintError("'errorsIndex' var is missing!");
return;
}
(void)records;
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;
}
createErrorClass(i, *defRec, os);
}
});
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) {
@ -130,9 +165,9 @@ void ErrorsBackend::run(llvm::raw_ostream &os) {
os << "#include \"serene/errors/base.h\"\n\n#include "
"<llvm/Support/Error.h>\n\n";
inNamespace("serene::errors", os,
[&](llvm::raw_ostream &os) { createNSBody(os); });
os << "#ifndef SERENE_ERRORS_ERRORS_H\n#define SERENE_ERRORS_ERRORS_H\n\n";
createNSBody(os);
os << "#endif\n";
}
void emitErrors(llvm::RecordKeeper &rk, llvm::raw_ostream &os) {