Eval: Add special form "if"
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user