Add the read and print functionality to the repl

This commit is contained in:
Sameer Rahmani 2021-10-24 23:34:28 +01:00
parent 3fb6fb3740
commit fc11896c28
21 changed files with 226 additions and 89 deletions

View File

@ -108,6 +108,7 @@ on ADF
* TODOs
** Bootstrap*
*** TODO Use =const= where ever it makes sense
*** TODO Create different pass pipeline for different compilation phases
So we can use them directly via command line, like -O1 for example

View File

@ -96,7 +96,7 @@ public:
/// Insert the given `ns` into the context. The Context object is
/// the owner of all the namespaces. The `ns` will overwrite any
/// namespace with the same name.
void insertNS(const std::shared_ptr<Namespace> &ns);
void insertNS(NSPtr &ns);
/// Sets the n ame of the current namespace in the context and return
/// a boolean indicating the status of this operation. The operation
@ -107,8 +107,8 @@ public:
Namespace &getCurrentNS();
/// Lookup the namespace with the give name in the current context and
/// return a shared pointer to it or a `nullptr` in it doesn't exist.
std::shared_ptr<Namespace> getNS(llvm::StringRef ns_name);
/// return a pointer to it or a `nullptr` in it doesn't exist.
Namespace *getNS(llvm::StringRef ns_name);
SereneContext()
: pm(&mlirContext), diagEngine(makeDiagnosticEngine(*this)),
@ -134,8 +134,8 @@ public:
CompilationPhase getTargetPhase() { return targetPhase; };
int getOptimizatioLevel();
NSPtr readNamespace(const std::string &name);
NSPtr readNamespace(std::string name, reader::LocationRange loc);
MaybeNS readNamespace(const std::string &name);
MaybeNS readNamespace(const std::string &name, reader::LocationRange loc);
private:
CompilationPhase targetPhase;
@ -143,7 +143,7 @@ private:
// The namespace table. Every namespace that needs to be compiled has
// to register itself with the context and appear on this table.
// This table acts as a cache as well.
std::map<std::string, std::shared_ptr<Namespace>> namespaces;
std::map<std::string, NSPtr> namespaces;
// Why string vs pointer? We might rewrite the namespace and
// holding a pointer means that it might point to the old version

View File

@ -20,14 +20,18 @@
#define SERENE_DIAGNOSTICS_H
#include "serene/errors/constants.h"
#include "serene/errors/error.h"
#include "serene/reader/location.h"
#include "serene/source_mgr.h"
#include <serene/export.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/raw_ostream.h>
#include <memory>
#include <mlir/IR/Diagnostics.h>
#include <memory>
namespace serene {
class SereneContext;
class DiagnosticEngine;
@ -81,6 +85,9 @@ public:
void emitSyntaxError(reader::LocationRange loc, errors::ErrorVariant &e,
llvm::StringRef msg = "");
void emit(const errors::ErrorPtr &err);
void emit(const errors::ErrorTree &errs);
/// Throw out an error with the given `msg` and terminate the execution
void panic(llvm::StringRef msg);
};
@ -89,9 +96,11 @@ public:
/// `SereneContext`
std::unique_ptr<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx);
/// Throw out an error with the given `msg` and terminate the execution
void panic(SereneContext &ctx, llvm::StringRef msg);
/// Throw out an error with the given `msg` and terminate the execution.
SERENE_EXPORT void panic(SereneContext &ctx, llvm::StringRef msg);
/// Throw the give `ErrorTree` \p errs and terminate the execution.
SERENE_EXPORT void throwErrors(SereneContext &ctx, errors::ErrorTree &errs);
} // namespace serene
#endif

View File

@ -28,6 +28,13 @@
namespace serene {
namespace errors {
/// This enum represent the expression type and **not** the value type.
enum class ErrType {
Syntax,
Semantic,
Compile,
};
enum ErrID {
E0000 = 0,
E0001,

View File

@ -19,23 +19,25 @@
#ifndef SERENE_ERRORS_ERROR_H
#define SERENE_ERRORS_ERROR_H
#include "serene/context.h"
#include "serene/errors/constants.h"
#include "serene/errors/traits.h"
#include "serene/reader/location.h"
#include "serene/reader/traits.h"
#include "serene/traits.h"
//#include "serene/exprs/expression.h"
#include <llvm/Support/Error.h>
#include <llvm/ADT/Optional.h>
namespace serene::reader {
class LoccationRange;
} // namespace serene::reader
namespace serene::errors {
class Error;
/// This enum represent the expression type and **not** the value type.
enum class ErrType {
Syntax,
Semantic,
Compile,
};
using ErrorPtr = std::shared_ptr<errors::Error>;
// tree? Yupe, Errors can be stackable which makes a vector of them a tree
using ErrorTree = std::vector<ErrorPtr>;
using OptionalErrors = llvm::Optional<ErrorTree>;
/// This data structure represent the Lisp error. This type of expression
/// doesn't show up in the AST but the compiler might rewrite the AST
@ -56,10 +58,21 @@ public:
std::string toString() const;
reader::LocationRange &where();
ErrorVariant *getVariant();
std::string getMessage();
std::string &getMessage();
~Error() = default;
};
/// Creates a new Error in the give location \p loc, with the given
/// variant \p and an optional message \p msg and retuns a shared ptr
/// to the error. This is the official API to make errors.
ErrorPtr makeError(reader::LocationRange &loc, ErrorVariant &err,
llvm::StringRef msg = "msg");
/// Creates a new ErrorTree out of a new Error that creats from the input
/// argument and pass them to `makeError` function.
ErrorTree makeErrorTree(reader::LocationRange &loc, ErrorVariant &err,
llvm::StringRef msg = "msg");
}; // namespace serene::errors
#endif

View File

@ -19,7 +19,6 @@
#ifndef SERENE_ERRORS_TRAITS_H
#define SERENE_ERRORS_TRAITS_H
#include "serene/context.h"
#include "serene/errors/constants.h"
#include "serene/traits.h"

View File

@ -37,16 +37,11 @@ namespace exprs {
class Expression;
using Node = std::shared_ptr<Expression>;
using ErrorPtr = std::shared_ptr<errors::Error>;
// tree? Yupe, Errors can be stackable which makes a vector of them a tree
using ErrorTree = std::vector<ErrorPtr>;
using MaybeNode = Result<Node, ErrorTree>;
using Node = std::shared_ptr<Expression>;
using MaybeNode = Result<Node, errors::ErrorTree>;
using Ast = std::vector<Node>;
using MaybeAst = Result<Ast, ErrorTree>;
using MaybeAst = Result<Ast, errors::ErrorTree>;
static auto EmptyNode = MaybeNode::success(nullptr);
@ -118,8 +113,9 @@ std::shared_ptr<T> makeAndCast(Args &&...args) {
// of a `Result`. It should be useds where every we want to return a `MaybeNode`
/// successfully
template <typename T, typename... Args>
Result<Node, ErrorTree> makeSuccessfulNode(Args &&...args) {
return Result<Node, ErrorTree>::success(make<T>(std::forward<Args>(args)...));
Result<Node, errors::ErrorTree> makeSuccessfulNode(Args &&...args) {
return Result<Node, errors::ErrorTree>::success(
make<T>(std::forward<Args>(args)...));
};
/// The hlper function to create an Errorful `Result<T,...>` (`T` would be
@ -127,10 +123,10 @@ Result<Node, ErrorTree> makeSuccessfulNode(Args &&...args) {
/// passing any argument to this function to the `serene::errors::Error`
/// constructor.
template <typename T, typename... Args>
Result<T, ErrorTree> makeErrorful(Args &&...args) {
std::vector<ErrorPtr> v{
Result<T, errors::ErrorTree> makeErrorful(Args &&...args) {
std::vector<errors::ErrorPtr> v{
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
return Result<T, ErrorTree>::error(v);
return Result<T, errors::ErrorTree>::error(v);
};
/// The hlper function to create an Error node (The failure case of a MaybeNod)
@ -138,7 +134,7 @@ Result<T, ErrorTree> makeErrorful(Args &&...args) {
/// the `serene::errors::Error` constructor.
template <typename... Args>
MaybeNode makeErrorNode(Args &&...args) {
std::vector<ErrorPtr> v{
std::vector<errors::ErrorPtr> v{
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
return MaybeNode::error(v);
};

View File

@ -25,6 +25,8 @@
#include "serene/errors.h"
#include "serene/export.h"
#include "serene/exprs/expression.h"
#include "serene/namespace.h"
#include "serene/slir/generatable.h"
#include "serene/utils.h"
@ -162,6 +164,9 @@ public:
void registerSymbols(
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
symbolMap);
std::unique_ptr<exprs::Expression> eval(SereneContext &ctx,
std::string input);
};
} // namespace serene

View File

@ -29,6 +29,7 @@
#define SERENE_NAMESPACE_H
#include "serene/environment.h"
#include "serene/errors/error.h"
#include "serene/export.h"
#include "serene/slir/generatable.h"
#include "serene/traits.h"
@ -98,8 +99,8 @@ public:
/// Expand the current tree of the namespace with the given \p ast by
/// semantically analazing it first. If the give \p ast in not valid
/// it will emit an error.
mlir::LogicalResult expandTree(exprs::Ast &ast);
/// it will return analysis errors.
errors::OptionalErrors expandTree(exprs::Ast &ast);
/// Increase the function counter by one
uint nextFnCounter();
@ -127,10 +128,12 @@ public:
};
using NSPtr = std::shared_ptr<Namespace>;
using MaybeNS = Result<NSPtr, errors::ErrorTree>;
/// Create a naw namespace with the given `name` and optional `filename` and
/// return a shared pointer to it in the given Serene context. If the
/// `setCurrent` argument is set to true, the created NS will become the curret
/// namespace in the context
/// `setCurrent` argument is set to true, the created NS will become the
/// curret namespace in the context
SERENE_EXPORT NSPtr makeNamespace(SereneContext &ctx, llvm::StringRef name,
llvm::Optional<llvm::StringRef> filename,
bool setCurrent = true);

View File

@ -24,7 +24,7 @@
#include "serene/exprs/expression.h"
namespace serene::reader {
using AnalyzeResult = Result<exprs::Ast, std::vector<exprs::ErrorPtr>>;
using AnalyzeResult = Result<exprs::Ast, std::vector<errors::ErrorPtr>>;
/// The entry point to the Semantic analysis phase. It calls the `analyze`
/// method of each node in the given AST and creates a new AST that contains a
/// more comprehensive set of nodes in a semantically correct AST. If the

View File

@ -22,6 +22,7 @@
#include "serene/config.h"
#include "serene/context.h"
#include "serene/export.h"
#include "serene/exprs/expression.h"
#include "serene/source_mgr.h"
namespace serene {
@ -38,5 +39,42 @@ SERENE_EXPORT void registerSereneCLOptions();
/// Applies the global compiler options on the give \p SereneContext. This
/// function has to be called after `llvm::cl::ParseCommandLineOptions`.
SERENE_EXPORT void applySereneCLOptions(SereneContext &ctx);
/// Reads the the given \p input as a Serene source code in the given
/// \c SereneContext \p ctx and returns the possible AST tree of the input or an
/// error otherwise.
///
/// In case of an error Serene will throw the error messages vis the diagnostic
/// engine as well and the error that this function returns will be the generic
/// error message.
///
/// Be aware than this function reads the input in the context of the current
/// namespace. So for example if the input is somthing like:
///
/// (ns example.code) ....
///
/// and the current ns is `user` then if there is a syntax error in the input
/// the error will be reported under the `user` ns. This is logical because
/// this function reads the code and not evaluate it. the `ns` form has to be
/// evaluated in order to change the ns.
SERENE_EXPORT exprs::MaybeAst read(SereneContext &ctx, std::string &input);
/// Evaluates the given AST form \p input in the given \c SereneContext \p ctx
/// and retuns a new expression as the result or a possible error.
///
/// In case of an error Serene will throw the error messages vis the diagnostic
/// engine as well and the error that this function returns will be the
/// generic error message.
// SERENE_EXPORT exprs::MaybeNode eval(SereneContext &ctx, exprs::Ast input);
// TODO: Return a Serene String type instead of the std::string
// TODO: Create an overload to get a stream instead of the result string
/// Prints the given AST form \p input in the given \c SereneContext \p ctx
/// into the given \p result.
/// Note: print is a lisp action. Don't confuse it with a print function such
/// as `println`.
SERENE_EXPORT void print(SereneContext &ctx, const exprs::Ast &input,
std::string &result);
} // namespace serene
#endif

View File

@ -28,10 +28,11 @@
#include <llvm/Support/ErrorOr.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/SourceMgr.h>
#include <memory>
#include <mlir/IR/Diagnostics.h>
#include <mlir/Support/Timing.h>
#include <memory>
#define SMGR_LOG(...) \
DEBUG_WITH_TYPE("sourcemgr", llvm::dbgs() \
<< "[SMGR]: " << __VA_ARGS__ << "\n");
@ -173,15 +174,15 @@ public:
reader::LocationRange includeLoc);
/// Lookup for a file containing the namespace definition of with given
/// namespace name \p name and throw an error. In case that the file exists,
/// use the parser to read the file and create an AST from it. Then create a
/// namespace, set the its AST to the AST that we just read from the file and
/// return a shared pointer to the namespace.
/// namespace name \p name. In case that the file exists, it returns an
/// `ErrorTree`. It will use the parser to read the file and create an AST
/// from it. Then create a namespace, set the its AST to the AST that we just
/// read from the file and return a shared pointer to the namespace.
///
/// \p importLoc is a location in the source code where the give namespace is
/// imported.
NSPtr readNamespace(SereneContext &ctx, std::string name,
reader::LocationRange importLoc);
MaybeNS readNamespace(SereneContext &ctx, std::string name,
reader::LocationRange importLoc);
};
}; // namespace serene

View File

@ -29,13 +29,14 @@
namespace serene {
void SereneContext::insertNS(const std::shared_ptr<Namespace> &ns) {
namespaces[ns->name] = ns;
void SereneContext::insertNS(NSPtr &ns) {
auto nsName = ns->name;
namespaces[nsName] = ns;
};
std::shared_ptr<Namespace> SereneContext::getNS(llvm::StringRef ns_name) {
Namespace *SereneContext::getNS(llvm::StringRef ns_name) {
if (namespaces.count(ns_name.str()) != 0) {
return namespaces[ns_name.str()];
return namespaces[ns_name.str()].get();
}
return nullptr;
@ -90,14 +91,14 @@ int SereneContext::getOptimizatioLevel() {
return 3;
}
NSPtr SereneContext::readNamespace(const std::string &name) {
MaybeNS SereneContext::readNamespace(const std::string &name) {
auto loc = reader::LocationRange::UnknownLocation(name);
return readNamespace(name, loc);
};
NSPtr SereneContext::readNamespace(std::string name,
reader::LocationRange loc) {
MaybeNS SereneContext::readNamespace(const std::string &name,
reader::LocationRange loc) {
return sourceManager.readNamespace(*this, std::move(name), loc);
}

View File

@ -203,8 +203,24 @@ std::unique_ptr<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx) {
return std::make_unique<DiagnosticEngine>(ctx);
}
void DiagnosticEngine::emit(const errors::ErrorPtr &err) {
UNUSED(ctx);
// TODO: create a diag and print it
llvm::errs() << err->toString() << "\n";
};
void DiagnosticEngine::emit(const errors::ErrorTree &errs) {
for (const auto &e : errs) {
emit(e);
}
};
void panic(SereneContext &ctx, llvm::StringRef msg) {
ctx.diagEngine->panic(msg);
};
void throwErrors(SereneContext &ctx, errors::ErrorTree &errs) {
ctx.diagEngine->emit(errs);
};
} // namespace serene

View File

@ -20,6 +20,8 @@
#include <llvm/Support/FormatVariadic.h>
#include <memory>
namespace serene {
namespace errors {
@ -31,7 +33,18 @@ reader::LocationRange &Error::where() { return this->location; };
ErrorVariant *Error::getVariant() { return this->variant; }
std::string Error::getMessage() { return this->message; }
std::string &Error::getMessage() { return this->message; }
ErrorPtr makeError(reader::LocationRange &loc, ErrorVariant &err,
llvm::StringRef msg) {
return std::make_shared<Error>(loc, err, msg);
};
ErrorTree makeErrorTree(reader::LocationRange &loc, ErrorVariant &err,
llvm::StringRef msg) {
std::vector errs{makeError(loc, err, msg)};
return errs;
};
} // namespace errors
} // namespace serene

View File

@ -34,11 +34,12 @@
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/FormatVariadic.h>
#include <llvm/Support/raw_ostream.h>
#include <memory>
#include <mlir/IR/Builders.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/Verifier.h>
#include <mlir/Support/LogicalResult.h>
#include <memory>
#include <stdexcept>
#include <string>
@ -61,12 +62,12 @@ void Namespace::enqueueError(llvm::StringRef e) const {
exprs::Ast &Namespace::getTree() { return this->tree; }
mlir::LogicalResult Namespace::expandTree(exprs::Ast &ast) {
errors::OptionalErrors Namespace::expandTree(exprs::Ast &ast) {
if (ctx.getTargetPhase() == CompilationPhase::Parse) {
// we just want the raw AST
this->tree.insert(this->tree.end(), ast.begin(), ast.end());
return mlir::success();
return llvm::None;
}
// Run the semantic analyer on the ast and then if everything
@ -74,13 +75,12 @@ mlir::LogicalResult Namespace::expandTree(exprs::Ast &ast) {
auto maybeAst = reader::analyze(ctx, ast);
if (!maybeAst) {
enqueueError("Semantic analysis failed!");
return mlir::failure();
return maybeAst.getError();
}
auto semanticAst = std::move(maybeAst.getValue());
this->tree.insert(this->tree.end(), semanticAst.begin(), semanticAst.end());
return mlir::success();
return llvm::None;
}
uint Namespace::nextFnCounter() { return fn_counter++; };
@ -154,11 +154,12 @@ MaybeModule Namespace::compileToLLVM() {
Namespace::~Namespace(){};
std::shared_ptr<Namespace>
makeNamespace(SereneContext &ctx, llvm::StringRef name,
llvm::Optional<llvm::StringRef> filename, bool setCurrent) {
NSPtr makeNamespace(SereneContext &ctx, llvm::StringRef name,
llvm::Optional<llvm::StringRef> filename, bool setCurrent) {
auto nsPtr = std::make_shared<Namespace>(ctx, name, filename);
ctx.insertNS(nsPtr);
if (setCurrent) {
if (!ctx.setCurrentNS(nsPtr->name)) {
throw std::runtime_error("Couldn't set the current NS");

View File

@ -27,7 +27,7 @@ AnalyzeResult analyze(serene::SereneContext &ctx, exprs::Ast &inputAst) {
// TODO: Fetch the current namespace from the JIT engine later and if it is
// `nil` then the given `ast` has to start with a namespace definition.
std::vector<exprs::ErrorPtr> errors;
errors::ErrorTree errors;
exprs::Ast ast;
for (auto &element : inputAst) {

View File

@ -24,6 +24,11 @@
#include "serene/serene.h"
#include "serene/diagnostics.h"
#include "serene/exprs/expression.h"
#include "serene/reader/reader.h"
#include <llvm/ADT/None.h>
#include <llvm/Support/TargetSelect.h>
namespace serene {
@ -81,4 +86,24 @@ void applySereneCLOptions(SereneContext &ctx) {
#endif
}
SERENE_EXPORT exprs::MaybeAst read(SereneContext &ctx, std::string &input) {
auto &currentNS = ctx.getCurrentNS();
auto filename =
!currentNS.filename.hasValue()
? llvm::None
: llvm::Optional<llvm::StringRef>(currentNS.filename.getValue());
return reader::read(ctx, input, currentNS.name, filename);
};
// SERENE_EXPORT exprs::MaybeNode eval(SereneContext &ctx, exprs::Ast input){
// };
SERENE_EXPORT void print(SereneContext &ctx, const exprs::Ast &input,
std::string &result) {
UNUSED(ctx);
result = exprs::astToString(&input);
};
} // namespace serene

View File

@ -31,12 +31,13 @@
#include "serene/reader/semantics.h"
#include "serene/utils.h"
#include <system_error>
#include <llvm/Support/FormatVariadic.h>
#include <llvm/Support/Locale.h>
#include <llvm/Support/MemoryBufferRef.h>
#include <llvm/Support/Path.h>
#include <mlir/Support/LogicalResult.h>
#include <system_error>
namespace serene {
@ -77,8 +78,8 @@ SourceMgr::findFileInLoadPath(const std::string &name,
return newBufOrErr;
};
NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name,
reader::LocationRange importLoc) {
MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
reader::LocationRange importLoc) {
std::string importedFile;
SMGR_LOG("Attempt to load namespace: " + name);
@ -86,9 +87,9 @@ NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name,
if (!newBufOrErr) {
auto msg = llvm::formatv("Couldn't find namespace '{0}'", name);
ctx.diagEngine->emitSyntaxError(importLoc, errors::NSLoadError,
llvm::StringRef(msg));
return nullptr;
auto err = errors::makeErrorTree(importLoc, errors::NSLoadError,
llvm::StringRef(msg));
return MaybeNS::error(err);
}
auto bufferId = AddNewSourceBuffer(std::move(*newBufOrErr), importLoc);
@ -97,11 +98,9 @@ NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name,
if (bufferId == 0) {
auto msg = llvm::formatv("Couldn't add namespace '{0}'", name);
// TODO: enqueue the error here
ctx.diagEngine->emitSyntaxError(importLoc, errors::NSAddToSMError,
llvm::StringRef(msg));
return nullptr;
auto err = errors::makeErrorTree(importLoc, errors::NSAddToSMError,
llvm::StringRef(msg));
return MaybeNS::error(err);
}
// Since we moved the buffer to be added as the source storage we
@ -114,21 +113,17 @@ NSPtr SourceMgr::readNamespace(SereneContext &ctx, std::string name,
if (!maybeAst) {
SMGR_LOG("Couldn't Read namespace: " + name);
// The code that is calling this function has to flush the dia engine, so we
// don't have to emit an error
return nullptr;
return MaybeNS::error(maybeAst.getError());
}
// Create the NS and set the AST
auto ns =
makeNamespace(ctx, name, llvm::Optional(llvm::StringRef(importedFile)));
if (mlir::failed(ns->expandTree(maybeAst.getValue()))) {
auto errs = ns->expandTree(maybeAst.getValue());
if (errs) {
SMGR_LOG("Couldn't set the AST for namespace: " + name);
// The code that is calling this function has to flush the dia engine, so we
// don't have to emit an error
return nullptr;
return MaybeNS::error(errs.getValue());
}
return ns;

View File

@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serene/diagnostics.h"
#include "serene/linenoise.h"
#include "serene/serene.h"
@ -38,6 +39,7 @@ static std::string banner =
static std::string art = "\n";
// TODO: Change the default value to be OS agnostic
static cl::opt<std::string>
historyFile("h", cl::desc("The absolute path to the history file to use."),
cl::value_desc("filename"), cl::init("~/.serene-repl.history"));
@ -67,6 +69,7 @@ int main(int argc, char *argv[]) {
while (true) {
// Read line
std::string line;
std::string result;
std::string prompt = ctx->getCurrentNS().name + "> ";
auto quit = linenoise::Readline(prompt.c_str(), line);
@ -75,8 +78,15 @@ int main(int argc, char *argv[]) {
break;
}
llvm::outs() << "echo: '" << line << "'"
<< "\n";
auto maybeAst = serene::read(*ctx, line);
if (!maybeAst) {
serene::throwErrors(*ctx, maybeAst.getError());
continue;
}
serene::print(*ctx, maybeAst.getValue(), result);
llvm::outs() << result << "\n";
// Add text to history
linenoise::AddHistory(line.c_str());

View File

@ -287,13 +287,16 @@ int main(int argc, char *argv[]) {
}
}
auto runLoc = reader::LocationRange::UnknownLocation(inputNS);
auto ns = ctx->sourceManager.readNamespace(*ctx, inputNS, runLoc);
auto runLoc = reader::LocationRange::UnknownLocation(inputNS);
auto maybeNS = ctx->sourceManager.readNamespace(*ctx, inputNS, runLoc);
if (!ns) {
if (!maybeNS) {
throwErrors(*ctx, maybeNS.getError());
return (int)std::errc::no_such_file_or_directory;
}
auto ns = maybeNS.getValue();
ctx->insertNS(ns);
switch (emitAction) {
@ -303,6 +306,7 @@ int main(int argc, char *argv[]) {
llvm::outs() << exprs::astToString(&ast) << "\n";
return 0;
}
case Action::DumpSLIR:
case Action::DumpMLIR:
case Action::DumpLIR: {