Refactor the semantic analyzer to use the analysis state

* Refactor the semantic analyzer to use the new state struct
  which is just bunch of refs to the current ns and current env

* Add the `environments` vector to ns to store the environments
  and few helper functions to use it

* Add the `symbolList` (need a better name) to keep track of what
  symbols might be added to the namespace after calling `addTree`.
This commit is contained in:
Sameer Rahmani 2021-11-17 17:37:45 +00:00
parent 800105dbea
commit b3d1151a8b
22 changed files with 233 additions and 130 deletions

View File

@ -50,9 +50,11 @@ public:
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext & /*ctx*/) override;
void generateIR(serene::Namespace & /*ns*/,
mlir::ModuleOp & /*m*/) override{};
MaybeNode analyze(semantics::AnalysisState &state) override;
void generateIR(serene::Namespace &ns, mlir::ModuleOp &m) override {
UNUSED(ns);
UNUSED(m);
};
static bool classof(const Expression *e);
@ -61,9 +63,9 @@ public:
/// is supposed to be used in the semantic analysis phase.
///
/// \param ctx The semantic analysis context object.
/// \param env The environment that this node exists in.
/// \param list the list in question.
static MaybeNode make(SereneContext &ctx, List *list);
static MaybeNode make(semantics::AnalysisState &state, List *list);
~Call() = default;
};

View File

@ -49,8 +49,9 @@ public:
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext & /*ctx*/) override;
void generateIR(serene::Namespace & /*ns*/, mlir::ModuleOp & /*m*/) override;
MaybeNode analyze(semantics::AnalysisState &state) override;
void generateIR(serene::Namespace &ns, mlir::ModuleOp &m) override;
static bool classof(const Expression *e);
@ -58,9 +59,9 @@ public:
/// correct `def` form like `(def blah value)`. This function
/// is supposed to be used in the semantic analysis phase.
///
/// \param ctx The semantic analysis context object.
/// \param state is the semantic analysis state to use in creation time.
/// \param list the list containing the `def` form
static MaybeNode make(SereneContext &ctx, List *list);
static MaybeNode make(semantics::AnalysisState &state, List *list);
~Def() = default;
};

View File

@ -22,7 +22,9 @@
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/exprs/traits.h"
#include "serene/namespace.h"
#include "serene/reader/location.h"
#include "serene/semantics.h"
#include "serene/utils.h"
#include <mlir/IR/BuiltinOps.h>
@ -69,8 +71,8 @@ public:
/// another node. For example to change from a List containing `(def a b)`
/// to a `Def` node that represents defining a new binding.
///
/// \param ctx is the context object of the semantic analyzer.
virtual MaybeNode analyze(SereneContext &ctx) = 0;
/// \param state is the analysis state object of the semantic analyzer.
virtual MaybeNode analyze(semantics::AnalysisState &state) = 0;
/// Genenates the correspondig SLIR of the expressoin and attach it to the
/// given module.

View File

@ -53,8 +53,8 @@ public:
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext & /*ctx*/) override;
void generateIR(serene::Namespace & /*ns*/, mlir::ModuleOp & /*m*/) override;
MaybeNode analyze(semantics::AnalysisState &state) override;
void generateIR(serene::Namespace &ns, mlir::ModuleOp &m) override;
static bool classof(const Expression *e);
@ -63,9 +63,9 @@ public:
/// of a function, for exmaple: `(fn (args1 arg2) body)`.This function
/// is supposed to be used in the semantic analysis phase.
///
/// \param ctx The semantic analysis context object.
/// \param state is the semantic analysis state to use.
/// \param list the list containing the `fn` form
static MaybeNode make(SereneContext &ctx, List *list);
static MaybeNode make(semantics::AnalysisState &state, List *list);
void setName(std::string);
~Fn() = default;

View File

@ -72,7 +72,7 @@ public:
/// by the for loop.
std::vector<Node>::iterator end();
MaybeNode analyze(SereneContext &ctx) override;
MaybeNode analyze(semantics::AnalysisState &state) override;
// NOLINTNEXTLINE(readability-named-parameter)
void generateIR(serene::Namespace &, mlir::ModuleOp &) override{};

View File

@ -47,8 +47,8 @@ struct Number : public Expression {
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext &ctx) override;
void generateIR(serene::Namespace & /*ns*/, mlir::ModuleOp & /*m*/) override;
MaybeNode analyze(semantics::AnalysisState &state) override;
void generateIR(serene::Namespace &ns, mlir::ModuleOp &m) override;
// TODO: This is horrible, we need to fix it after the mvp
int toI64() const;

View File

@ -21,6 +21,7 @@
#include "serene/context.h"
#include "serene/exprs/expression.h"
#include "serene/namespace.h"
#include <llvm/ADT/StringRef.h>
@ -45,9 +46,11 @@ public:
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext & /*ctx*/) override;
void generateIR(serene::Namespace & /*ns*/,
mlir::ModuleOp & /*m*/) override{};
MaybeNode analyze(semantics::AnalysisState &state) override;
void generateIR(serene::Namespace &ns, mlir::ModuleOp &m) override {
UNUSED(ns);
UNUSED(m);
};
~Symbol() = default;

View File

@ -23,6 +23,8 @@
* - A namespace may or may not be assiciated with a file
* - The internal AST of a namespace is an evergrowing tree which may expand at
* any given time. For example via iteration of a REPL
* - `environments` vector is the owner of all the semantic envs
* - The first env in the `environments` is the root env.
*/
#ifndef SERENE_NAMESPACE_H
@ -62,8 +64,13 @@ using Node = std::shared_ptr<Expression>;
using Ast = std::vector<Node>;
} // namespace exprs
using MaybeModule = llvm::Optional<llvm::orc::ThreadSafeModule>;
using MaybeModuleOp = llvm::Optional<mlir::OwningOpRef<mlir::ModuleOp>>;
using MaybeModule = llvm::Optional<llvm::orc::ThreadSafeModule>;
using MaybeModuleOp = llvm::Optional<mlir::OwningOpRef<mlir::ModuleOp>>;
using SemanticEnv = Environment<std::string, exprs::Node>;
using SemanticEnvPtr = std::unique_ptr<SemanticEnv>;
using SemanticEnvironments = std::vector<SemanticEnvPtr>;
using Form = std::pair<SemanticEnv, exprs::Ast>;
using Forms = std::vector<Form>;
/// Serene's namespaces are the unit of compilation. Any code that needs to be
/// compiled has to be in a namespace. The official way to create a new
@ -81,27 +88,41 @@ private:
/// to pass the semantic analyzer.
exprs::Ast tree;
SemanticEnvironments environments;
std::vector<llvm::StringRef> symbolList;
public:
std::string name;
llvm::Optional<std::string> filename;
/// The root environment of the namespace on the semantic analysis phase.
/// Which is a mapping from names to AST nodes ( no evaluation ).
Environment<std::string, exprs::Node> semanticEnv;
/// Th root environmanet to store the MLIR value during the IR generation
/// phase.
Environment<llvm::StringRef, mlir::Value> symbolTable;
Namespace(SereneContext &ctx, llvm::StringRef ns_name,
llvm::Optional<llvm::StringRef> filename);
exprs::Ast &getTree();
/// Create a new environment with the give \p parent as the parent,
/// push the environment to the internal environment storage and
/// return a reference to it. The namespace itself is the owner of
/// environments.
SemanticEnv &createEnv(SemanticEnv *parent);
/// 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 return analysis errors.
errors::OptionalErrors expandTree(exprs::Ast &ast);
/// Return a referenece to the top level (root) environment of ns.
SemanticEnv &getRootEnv();
/// Define a new binding in the root environment with the given \p name
/// and the given \p node. Defining a new binding with a name that
/// already exists in legal and will overwrite the previous binding and
/// the given name will point to a new value from now on.
mlir::LogicalResult define(std::string &name, exprs::Node &node);
/// Add the given \p ast to the namespace and return any possible error.
/// The given \p ast will be added to a vector of ASTs that the namespace
/// have. In a normal compilation a Namespace will have a vector of ASTs
/// with only one element, but in a REPL like environment it might have
/// many elements.
///
/// This function runs the semantic analyzer on the \p ast as well.
errors::OptionalErrors addTree(exprs::Ast &ast);
exprs::Ast &getTree();
/// Increase the function counter by one
uint nextFnCounter();

View File

@ -1,43 +0,0 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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_READER_SEMANTICS_H
#define SERENE_READER_SEMANTICS_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/exprs/expression.h"
namespace serene::reader {
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
/// `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. Also please note that in **Serene** Semantic errors
/// represented as AST nodes as well. So you should expect an `analyze` method
/// of a node to return a `Result<node>::Success(Error...)` in case of a
/// semantic error.
///
/// \param ctx The semantic analysis context
/// \param inputAst The raw AST to analyze and possibly rewrite.
AnalyzeResult analyze(serene::SereneContext &ctx, exprs::Ast &inputAst);
}; // namespace serene::reader
#endif

View File

@ -0,0 +1,75 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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_SEMANTICS_H
#define SERENE_SEMANTICS_H
#include "serene/environment.h"
#include "serene/errors/error.h"
#include "serene/utils.h"
#include <llvm/ADT/StringRef.h>
#include <memory>
namespace serene {
namespace exprs {
class Expression;
using Node = std::shared_ptr<Expression>;
using Ast = std::vector<Node>;
}; // namespace exprs
class Namespace;
using SemanticEnv = Environment<std::string, exprs::Node>;
namespace semantics {
using AnalyzeResult = Result<exprs::Ast, std::vector<errors::ErrorPtr>>;
/// This struct represent the state necessary for each analysis job.
struct AnalysisState {
Namespace &ns;
SemanticEnv &env;
AnalysisState(Namespace &ns, SemanticEnv &env) : ns(ns), env(env){};
std::unique_ptr<AnalysisState> moveToNewEnv();
};
/// Create an new `AnalysisState` by forwarding all parameters off this
/// function directly to the ctor of `AnalysisState` and returns a
/// unique pointer to the state.
template <typename... Args>
std::unique_ptr<AnalysisState> makeAnalysisState(Args &&...args) {
return std::make_unique<AnalysisState>(std::forward<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.
/// \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);
} // namespace semantics
} // namespace serene
#endif

View File

@ -43,6 +43,7 @@ add_library(serene
namespace.cpp
source_mgr.cpp
diagnostics.cpp
semantics.cpp
# jit.cpp
jit/engine.cpp
@ -50,7 +51,6 @@ add_library(serene
# Reader
reader/reader.cpp
reader/semantics.cpp
# Errors
errors/error.cpp

View File

@ -23,7 +23,7 @@
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
#include "serene/exprs/symbol.h"
#include "serene/reader/semantics.h"
#include "serene/namespace.h"
#include "serene/utils.h"
#include <llvm/Support/Casting.h>
@ -40,8 +40,9 @@ std::string Call::toString() const {
astToString(&this->params));
}
MaybeNode Call::analyze(SereneContext &ctx) {
UNUSED(ctx);
MaybeNode Call::analyze(semantics::AnalysisState &state) {
UNUSED(state);
return EmptyNode;
};
@ -49,12 +50,13 @@ bool Call::classof(const Expression *e) {
return e->getType() == ExprType::Call;
};
MaybeNode Call::make(SereneContext &ctx, List *list) {
MaybeNode Call::make(semantics::AnalysisState &state, List *list) {
// TODO: replace this with a runtime check
assert((list->count() != 0) && "Empty call? Seriously ?");
// Let's find out what is the first element of the list
auto maybeFirst = list->elements[0]->analyze(ctx);
auto maybeFirst = list->elements[0]->analyze(state);
if (!maybeFirst) {
// There's something wrong with the first element. Return the error
@ -90,9 +92,7 @@ MaybeNode Call::make(SereneContext &ctx, List *list) {
llvm_unreachable("Couldn't case to Symbol while the type is symbol!");
}
// TODO: Lookup the symbol in the namespace via a method that looks
// into the current environment.
auto maybeResult = ctx.getCurrentNS().semanticEnv.lookup(sym->name);
auto maybeResult = state.env.lookup(sym->name);
if (!maybeResult.hasValue()) {
std::string msg =
@ -100,7 +100,7 @@ MaybeNode Call::make(SereneContext &ctx, List *list) {
return makeErrorful<Node>(sym->location, errors::CantResolveSymbol, msg);
}
targetNode = maybeResult.getValue();
targetNode = std::move(maybeResult.getValue());
break;
}
@ -127,7 +127,7 @@ MaybeNode Call::make(SereneContext &ctx, List *list) {
}
};
auto analyzedParams = reader::analyze(ctx, rawParams);
auto analyzedParams = semantics::analyze(state, rawParams);
if (!analyzedParams) {
return MaybeNode::error(analyzedParams.getError());

View File

@ -39,8 +39,9 @@ std::string Def::toString() const {
this->value->toString());
}
MaybeNode Def::analyze(SereneContext &ctx) {
UNUSED(ctx);
MaybeNode Def::analyze(semantics::AnalysisState &state) {
UNUSED(state);
return EmptyNode;
};
@ -48,7 +49,7 @@ bool Def::classof(const Expression *e) {
return e->getType() == ExprType::Def;
};
MaybeNode Def::make(SereneContext &ctx, List *list) {
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());
@ -70,7 +71,7 @@ MaybeNode Def::make(SereneContext &ctx, List *list) {
}
// Analyze the value
MaybeNode value = list->elements[2]->analyze(ctx);
MaybeNode value = list->elements[2]->analyze(state);
Node analyzedValue;
// TODO: To refactor this logic into a generic function
@ -99,8 +100,7 @@ MaybeNode Def::make(SereneContext &ctx, List *list) {
tmp->setName(binding->name);
}
auto result = ctx.getCurrentNS().semanticEnv.insert_symbol(binding->name,
analyzedValue);
auto result = state.ns.define(binding->name, analyzedValue);
if (result.succeeded()) {
return makeSuccessfulNode<Def>(list->location, binding->name,

View File

@ -22,7 +22,6 @@
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
#include "serene/exprs/symbol.h"
#include "serene/reader/semantics.h"
#include "serene/slir/dialect.h"
#include "serene/slir/utils.h"
@ -51,8 +50,9 @@ std::string Fn::toString() const {
this->body.empty() ? "<>" : astToString(&this->body));
}
MaybeNode Fn::analyze(SereneContext &ctx) {
UNUSED(ctx);
MaybeNode Fn::analyze(semantics::AnalysisState &state) {
UNUSED(state);
return EmptyNode;
};
@ -60,7 +60,10 @@ bool Fn::classof(const Expression *e) { return e->getType() == ExprType::Fn; };
void Fn::setName(std::string n) { this->name = std::move(n); };
MaybeNode Fn::make(SereneContext &ctx, List *list) {
MaybeNode Fn::make(semantics::AnalysisState &state, List *list) {
auto &ctx = state.ns.getContext();
// TODO: Add support for docstring as the 3rd argument (4th element)
if (list->count() < 2) {
return makeErrorful<Node>(list->elements[0]->location, errors::FnNoArgsList,
@ -89,8 +92,12 @@ MaybeNode Fn::make(SereneContext &ctx, List *list) {
// If there is a body for this function analyze the body and set
// the retuned ast as the final body
if (list->count() > 2) {
body = std::vector<Node>(list->begin() + 2, list->end());
auto maybeAst = reader::analyze(ctx, body);
body = std::vector<Node>(list->begin() + 2, list->end());
// TODO: call state.moveToNewEnv to create a new env and set the
// arguments into the new env.
auto maybeAst = semantics::analyze(state, body);
if (!maybeAst) {
return MaybeNode::error(std::move(maybeAst.getError()));

View File

@ -58,7 +58,8 @@ std::string List::toString() const {
return llvm::formatv("<List {0}>", s);
};
MaybeNode List::analyze(SereneContext &ctx) {
MaybeNode List::analyze(semantics::AnalysisState &state) {
if (!elements.empty()) {
auto *first = elements[0].get();
@ -67,16 +68,16 @@ MaybeNode List::analyze(SereneContext &ctx) {
if (sym != nullptr) {
if (sym->name == "def") {
return Def::make(ctx, this);
return Def::make(state, this);
}
if (sym->name == "fn") {
return Fn::make(ctx, this);
return Fn::make(state, this);
}
}
}
return Call::make(ctx, this);
return Call::make(state, this);
}
return EmptyNode;

View File

@ -38,8 +38,9 @@ std::string Number::toString() const {
return llvm::formatv("<Number {0}>", value);
}
MaybeNode Number::analyze(SereneContext &ctx) {
UNUSED(ctx);
MaybeNode Number::analyze(semantics::AnalysisState &state) {
UNUSED(state);
return EmptyNode;
};

View File

@ -32,8 +32,9 @@ std::string Symbol::toString() const {
return llvm::formatv("<Symbol {0}>", this->name);
}
MaybeNode Symbol::analyze(SereneContext &ctx) {
UNUSED(ctx);
MaybeNode Symbol::analyze(semantics::AnalysisState &state) {
UNUSED(state);
return EmptyNode;
};

View File

@ -95,7 +95,7 @@ llvm::Error NSLayer::add(orc::ResourceTrackerSP &rt, llvm::StringRef nsname,
orc::SymbolFlagsMap NSLayer::getInterface(serene::Namespace &ns) {
orc::SymbolFlagsMap Symbols;
for (auto &k : ns.semanticEnv) {
for (auto &k : ns.getRootEnv()) {
auto flags = llvm::JITSymbolFlags::Exported;
auto name = k.getFirst();
auto expr = k.getSecond();

View File

@ -28,7 +28,7 @@
#include "serene/errors/constants.h"
#include "serene/exprs/expression.h"
#include "serene/llvm/IR/Value.h"
#include "serene/reader/semantics.h"
#include "serene/semantics.h"
#include "serene/slir/slir.h"
#include <llvm/ADT/StringRef.h>
@ -54,32 +54,62 @@ Namespace::Namespace(SereneContext &ctx, llvm::StringRef ns_name,
if (filename.hasValue()) {
this->filename.emplace(filename.getValue().str());
}
// Create the root environment
createEnv(nullptr);
};
void Namespace::enqueueError(llvm::StringRef e) const {
ctx.diagEngine->enqueueError(e);
}
SemanticEnv &Namespace::createEnv(SemanticEnv *parent) {
auto env = std::make_unique<SemanticEnv>(parent);
environments.push_back(std::move(env));
return *environments.back();
};
SemanticEnv &Namespace::getRootEnv() {
assert(environments.empty() && "Root env is not created!");
return *environments.front();
};
mlir::LogicalResult Namespace::define(std::string &name, exprs::Node &node) {
auto &rootEnv = getRootEnv();
if (failed(rootEnv.insert_symbol(name, node))) {
return mlir::failure();
}
symbolList.push_back(name);
return mlir::success();
}
exprs::Ast &Namespace::getTree() { return this->tree; }
errors::OptionalErrors Namespace::addTree(exprs::Ast &ast) {
errors::OptionalErrors Namespace::expandTree(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;
}
auto &rootEnv = getRootEnv();
auto state = semantics::makeAnalysisState(*this, rootEnv);
// Run the semantic analyer on the ast and then if everything
// is ok expand the currnt tree by the semantically correct ast.
auto maybeAst = reader::analyze(ctx, ast);
// is ok add the form to the tree and forms
auto maybeForm = semantics::analyze(*state, ast);
if (!maybeAst) {
return maybeAst.getError();
if (!maybeForm) {
return maybeForm.getError();
}
auto semanticAst = std::move(maybeAst.getValue());
auto semanticAst = std::move(maybeForm.getValue());
this->tree.insert(this->tree.end(), semanticAst.begin(), semanticAst.end());
return llvm::None;
}

View File

@ -16,22 +16,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serene/reader/semantics.h"
#include "serene/semantics.h"
#include "serene/context.h"
#include "serene/exprs/expression.h"
#include "serene/namespace.h"
namespace serene::reader {
namespace serene::semantics {
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::unique_ptr<AnalysisState> AnalysisState::moveToNewEnv() {
auto &newEnv = ns.createEnv(&env);
return makeAnalysisState(ns, newEnv);
};
AnalyzeResult analyze(AnalysisState &state, exprs::Ast &forms) {
errors::ErrorTree errors;
exprs::Ast ast;
for (auto &element : inputAst) {
auto maybeNode = element->analyze(ctx);
for (auto &element : forms) {
auto maybeNode = element->analyze(state);
// Is it a `success` result
if (maybeNode) {
@ -61,4 +64,4 @@ AnalyzeResult analyze(serene::SereneContext &ctx, exprs::Ast &inputAst) {
return AnalyzeResult::error(std::move(errors));
};
}; // namespace serene::reader
}; // namespace serene::semantics

View File

@ -28,7 +28,6 @@
#include "serene/namespace.h"
#include "serene/reader/location.h"
#include "serene/reader/reader.h"
#include "serene/reader/semantics.h"
#include "serene/utils.h"
#include <system_error>
@ -125,7 +124,7 @@ MaybeNS SourceMgr::readNamespace(SereneContext &ctx, std::string name,
auto ns =
makeNamespace(ctx, name, llvm::Optional(llvm::StringRef(importedFile)));
auto errs = ns->expandTree(maybeAst.getValue());
auto errs = ns->addTree(maybeAst.getValue());
if (errs) {
SMGR_LOG("Couldn't set the AST for namespace: " + name);
return MaybeNS::error(errs.getValue());

View File

@ -20,7 +20,7 @@
#include "serene/namespace.h"
#include "serene/reader/location.h"
#include "serene/reader/reader.h"
#include "serene/reader/semantics.h"
#include "serene/semantics.h"
#include "serene/serene.h"
#include "serene/slir/generatable.h"
#include "serene/slir/slir.h"