Analyze the value in the 'def' form
This commit is contained in:
parent
8242249dca
commit
4aee3413ea
|
@ -55,8 +55,12 @@ public:
|
|||
static bool classof(const Expression *e);
|
||||
|
||||
/// Create a Def node out a list. The list should contain the
|
||||
/// correct `def` form like `(def blah value)`.
|
||||
static maybe_node make(List *);
|
||||
/// 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 list the list containing the `def` form
|
||||
static maybe_node make(reader::SemanticContext &ctx, List *list);
|
||||
~Def() = default;
|
||||
};
|
||||
|
||||
|
|
|
@ -60,8 +60,13 @@ public:
|
|||
|
||||
/// Creates a function node out of a function definition
|
||||
/// in a list. the list has to contain the correct definition
|
||||
/// of a function, for exmaple: `(fn (args1 arg2) body)`
|
||||
static maybe_node make(List *);
|
||||
/// 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 list the list containing the `fn` form
|
||||
static maybe_node make(reader::SemanticContext &ctx, List *list);
|
||||
|
||||
~Fn() = default;
|
||||
};
|
||||
|
||||
|
|
|
@ -46,26 +46,48 @@ bool Def::classof(const Expression *e) {
|
|||
return e->getType() == ExprType::Def;
|
||||
};
|
||||
|
||||
maybe_node Def::make(List *list) {
|
||||
maybe_node Def::make(reader::SemanticContext &ctx, 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 Result<node>::success(makeAndCast<errors::Error>(
|
||||
&errors::DefWrongNumberOfArgs, list->elements[0], msg));
|
||||
}
|
||||
|
||||
// Make sure that the list starts with a `def`
|
||||
Symbol *defSym = llvm::dyn_cast<Symbol>(list->elements[0].get());
|
||||
assert((defSym && defSym->name == "def") &&
|
||||
"The first element of the list should be a 'def'.");
|
||||
|
||||
// Make sure that the first argument is a Symbol
|
||||
Symbol *binding = llvm::dyn_cast<Symbol>(list->elements[1].get());
|
||||
|
||||
if (!binding) {
|
||||
return Result<node>::success(makeAndCast<errors::Error>(
|
||||
&errors::DefExpectSymbol, list->elements[1], ""));
|
||||
}
|
||||
|
||||
node def = exprs::make<Def>(list->location, binding->name, list->elements[2]);
|
||||
// Analyze the value
|
||||
maybe_node value = list->elements[2]->analyze(ctx);
|
||||
node analyzedValue;
|
||||
|
||||
if (value) {
|
||||
// Success value
|
||||
auto &valueNode = value.getValue();
|
||||
|
||||
if (valueNode) {
|
||||
// A rewrite is necessary
|
||||
analyzedValue = valueNode;
|
||||
} else {
|
||||
// no rewrite
|
||||
analyzedValue = list->elements[2];
|
||||
}
|
||||
} else {
|
||||
// Error value
|
||||
return value;
|
||||
}
|
||||
|
||||
node def = exprs::make<Def>(list->location, binding->name, analyzedValue);
|
||||
return Result<node>::success(def);
|
||||
};
|
||||
} // namespace exprs
|
||||
|
|
|
@ -47,7 +47,7 @@ maybe_node Fn::analyze(reader::SemanticContext &ctx) {
|
|||
|
||||
bool Fn::classof(const Expression *e) { return e->getType() == ExprType::Fn; };
|
||||
|
||||
maybe_node Fn::make(List *list) {
|
||||
maybe_node Fn::make(reader::SemanticContext &ctx, List *list) {
|
||||
// TODO: Add support for docstring as the 3rd argument (4th element)
|
||||
if (list->count() < 2) {
|
||||
std::string msg =
|
||||
|
|
|
@ -64,11 +64,11 @@ maybe_node List::analyze(reader::SemanticContext &ctx) {
|
|||
|
||||
if (sym) {
|
||||
if (sym->name == "def") {
|
||||
return Def::make(this);
|
||||
return Def::make(ctx, this);
|
||||
}
|
||||
|
||||
if (sym->name == "fn") {
|
||||
return Fn::make(this);
|
||||
return Fn::make(ctx, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,12 @@ TEST_CASE("List semantic analysis of 'def'", "[semantic]") {
|
|||
afterAst = analyzer.analyze(ast.getValue());
|
||||
REQUIRE(afterAst);
|
||||
CHECK(astToString(&afterAst.getValue()) == "<Def a -> <Symbol b>>");
|
||||
|
||||
ast = reader::read("(def a (fn () a))");
|
||||
afterAst = analyzer.analyze(ast.getValue());
|
||||
REQUIRE(afterAst);
|
||||
CHECK(astToString(&afterAst.getValue()) ==
|
||||
"<Def a -> <Fn Anonymous <List -> to <Symbol a>>>");
|
||||
}
|
||||
|
||||
TEST_CASE("List semantic analysis for 'fn'", "[semantic]") {
|
||||
|
@ -107,7 +113,8 @@ TEST_CASE("List semantic analysis for 'fn'", "[semantic]") {
|
|||
auto ast = reader::read("(fn)");
|
||||
auto afterAst = analyzer.analyze(ast.getValue());
|
||||
REQUIRE(afterAst);
|
||||
CHECK(astToString(&afterAst.getValue()) == "<Error E3: The argument list is mandatory.>");
|
||||
CHECK(astToString(&afterAst.getValue()) ==
|
||||
"<Error E3: The argument list is mandatory.>");
|
||||
|
||||
ast = reader::read("(fn ())");
|
||||
afterAst = analyzer.analyze(ast.getValue());
|
||||
|
@ -117,12 +124,14 @@ TEST_CASE("List semantic analysis for 'fn'", "[semantic]") {
|
|||
ast = reader::read("(fn (a b c) a a a)");
|
||||
afterAst = analyzer.analyze(ast.getValue());
|
||||
REQUIRE(afterAst);
|
||||
CHECK(astToString(&afterAst.getValue()) == "<Fn Anonymous <List -> to <Symbol a> <Symbol a> <Symbol a>>");
|
||||
CHECK(astToString(&afterAst.getValue()) ==
|
||||
"<Fn Anonymous <List -> to <Symbol a> <Symbol a> <Symbol a>>");
|
||||
|
||||
ast = reader::read("(fn () a b)");
|
||||
afterAst = analyzer.analyze(ast.getValue());
|
||||
REQUIRE(afterAst);
|
||||
CHECK(astToString(&afterAst.getValue()) == "<Fn Anonymous <List -> to <Symbol a> <Symbol b>>");
|
||||
CHECK(astToString(&afterAst.getValue()) ==
|
||||
"<Fn Anonymous <List -> to <Symbol a> <Symbol b>>");
|
||||
}
|
||||
} // namespace exprs
|
||||
} // namespace serene
|
||||
|
|
Loading…
Reference in New Issue