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