Setup the minimal semantic analysis foundation
This commit is contained in:
parent
f614d35b7f
commit
806987b0ad
|
@ -34,7 +34,7 @@ namespace errors {
|
|||
enum ErrID {
|
||||
E0000,
|
||||
E0001,
|
||||
|
||||
E0002,
|
||||
};
|
||||
|
||||
struct ErrorVariant {
|
||||
|
@ -52,8 +52,13 @@ static ErrorVariant
|
|||
DefExpectSymbol(E0001, "The first argument to 'def' has to be a Symbol.",
|
||||
"");
|
||||
|
||||
static std::map<ErrID, ErrorVariant *> ErrDesc = {{E0000, &UnknownError},
|
||||
{E0001, &DefExpectSymbol}};
|
||||
static ErrorVariant DefWrongNumberOfArgs(
|
||||
E0002, "Wrong number of arguments is passed to the 'def' form.", "");
|
||||
|
||||
static std::map<ErrID, ErrorVariant *> ErrDesc = {
|
||||
{E0000, &UnknownError},
|
||||
{E0001, &DefExpectSymbol},
|
||||
{E0002, &DefWrongNumberOfArgs}};
|
||||
|
||||
} // namespace errors
|
||||
} // namespace serene
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
maybe_node analyze(reader::SemanticContext &);
|
||||
|
||||
static bool classof(const Expression *e);
|
||||
static std::shared_ptr<errors::Error> isValid(const List *);
|
||||
static std::shared_ptr<errors::Error> isValid(List *);
|
||||
|
||||
~Def() = default;
|
||||
};
|
||||
|
|
|
@ -107,6 +107,7 @@ std::shared_ptr<T> makeAndCast(Args &&...args) {
|
|||
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||
};
|
||||
|
||||
std::string toString(ast &);
|
||||
void dump(ast &);
|
||||
|
||||
} // namespace exprs
|
||||
|
|
|
@ -33,9 +33,7 @@ serene::exprs::ExprType Error::getType() const {
|
|||
};
|
||||
|
||||
std::string Error::toString() const {
|
||||
return llvm::formatv(
|
||||
"<Error [loc: {0} | {1}]: E{2}: {3}>", this->location.start.toString(),
|
||||
this->location.end.toString(), this->variant->id, this->message);
|
||||
return llvm::formatv("<Error E{0}: {1}>", this->variant->id, this->message);
|
||||
}
|
||||
|
||||
serene::exprs::maybe_node Error::analyze(reader::SemanticContext &ctx) {
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
*/
|
||||
|
||||
#include "serene/exprs/def.h"
|
||||
#include "serene/errors/error.h"
|
||||
#include "serene/exprs/list.h"
|
||||
#include "serene/exprs/symbol.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
||||
namespace serene {
|
||||
|
@ -44,7 +46,21 @@ bool Def::classof(const Expression *e) {
|
|||
return e->getType() == ExprType::Def;
|
||||
};
|
||||
|
||||
std::shared_ptr<errors::Error> Def::isValid(const List *list) {
|
||||
std::shared_ptr<errors::Error> Def::isValid(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 {}", list->count());
|
||||
return makeAndCast<errors::Error>(&errors::DefWrongNumberOfArgs,
|
||||
list->elements[0], msg);
|
||||
}
|
||||
|
||||
Symbol *binding = llvm::dyn_cast<Symbol>(list->elements[1].get());
|
||||
|
||||
if (!binding) {
|
||||
return makeAndCast<errors::Error>(&errors::DefExpectSymbol,
|
||||
list->elements[1], "");
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
} // namespace exprs
|
||||
|
|
|
@ -28,16 +28,22 @@
|
|||
namespace serene {
|
||||
namespace exprs {
|
||||
|
||||
/// Dump the given AST tree to the standard out
|
||||
void dump(ast &tree) {
|
||||
std::string result = "";
|
||||
|
||||
for (auto &node : tree) {
|
||||
result = llvm::formatv("{0} {1}", result, node->toString());
|
||||
std::string toString(ast &tree) {
|
||||
if (tree.size() == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
llvm::outs() << result << "\n";
|
||||
};
|
||||
std::string result = tree.at(0)->toString();
|
||||
|
||||
for (unsigned int i = 1; i < tree.size(); i++) {
|
||||
result = llvm::formatv("{0} {1}", result, tree.at(i)->toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Dump the given AST tree to the standard out
|
||||
void dump(ast &tree) { llvm::outs() << toString(tree) << "\n"; };
|
||||
|
||||
} // namespace exprs
|
||||
} // namespace serene
|
||||
|
|
|
@ -41,7 +41,7 @@ TEST_CASE("Error Expression", "[expression]") {
|
|||
exprs::node err = exprs::make<Error>(&DefExpectSymbol, sym, "Something Failed");
|
||||
|
||||
REQUIRE(err->getType() == exprs::ExprType::Error);
|
||||
CHECK(err->toString() == "<Error [loc: 2:20:40 | 3:30:80]: E1: Something Failed>");
|
||||
CHECK(err->toString() == "<Error E1: Something Failed>");
|
||||
|
||||
auto error = llvm::dyn_cast<Error>(err.get());
|
||||
CHECK(error->target == sym);
|
||||
|
|
|
@ -23,7 +23,10 @@
|
|||
*/
|
||||
|
||||
#include "../test_helpers.cpp.inc"
|
||||
#include "serene/exprs/expression.h"
|
||||
#include "serene/exprs/list.h"
|
||||
#include "serene/reader/reader.h"
|
||||
#include "serene/reader/semantics.h"
|
||||
#include "serene/exprs/symbol.h"
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
|
@ -75,5 +78,19 @@ TEST_CASE("List Expression", "[expression]") {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
TEST_CASE("List semantic analysis", "[semantic]") {
|
||||
reader::Semantics analyzer;
|
||||
auto r = new reader::Reader("(def (a b) 4)");
|
||||
auto ast = r->read().getValue();
|
||||
|
||||
//auto &ast = maybeAst.getValue();
|
||||
auto afterAst = analyzer.analyze(ast);
|
||||
|
||||
|
||||
REQUIRE(afterAst);
|
||||
CHECK(toString(afterAst.getValue()) == "<Error E1: >");
|
||||
delete r;
|
||||
}
|
||||
} // namespace exprs
|
||||
} // namespace serene
|
||||
|
|
Loading…
Reference in New Issue