Eval: Add special form "if"

This commit is contained in:
Riyyi
2023-03-28 22:50:57 +02:00
parent 38d8daa9d0
commit bbced6f487
2 changed files with 25 additions and 0 deletions
+24
View File
@@ -60,6 +60,9 @@ ASTNodePtr Eval::evalImpl(ASTNodePtr ast, EnvironmentPtr env)
if (symbol == "do") {
return evalDo(nodes, env);
}
if (symbol == "if") {
return evalIf(nodes, env);
}
}
// Function call
@@ -219,6 +222,27 @@ ASTNodePtr Eval::evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
return evalImpl(nodes.back(), env);
}
ASTNodePtr Eval::evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
{
if (nodes.size() != 2 && nodes.size() != 3) {
Error::the().addError(format("wrong number of arguments: if, {}", nodes.size()));
return nullptr;
}
auto first_argument = *nodes.begin();
auto second_argument = *std::next(nodes.begin());
auto third_argument = (nodes.size() == 3) ? *std::next(std::next(nodes.begin())) : makePtr<Value>(Value::Nil);
auto first_evaluated = evalImpl(first_argument, env);
if (!is<Value>(first_evaluated.get())
|| std::static_pointer_cast<Value>(first_evaluated)->state() == Value::True) {
return evalImpl(second_argument, env);
}
else {
return evalImpl(third_argument, env);
}
}
ASTNodePtr Eval::apply(std::shared_ptr<List> evaluated_list)
{
if (evaluated_list == nullptr) {
+1
View File
@@ -28,6 +28,7 @@ private:
ASTNodePtr evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
ASTNodePtr evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
ASTNodePtr evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
ASTNodePtr evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
ASTNodePtr apply(std::shared_ptr<List> evaluated_list);
ASTNodePtr m_ast;