From bbced6f48720bff3c1c70dea250970d3ba92a25b Mon Sep 17 00:00:00 2001 From: Riyyi Date: Tue, 28 Mar 2023 22:50:57 +0200 Subject: [PATCH] Eval: Add special form "if" --- src/eval.cpp | 24 ++++++++++++++++++++++++ src/eval.h | 1 + 2 files changed, 25 insertions(+) diff --git a/src/eval.cpp b/src/eval.cpp index cb151f4..89e501e 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -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& nodes, EnvironmentPtr env) return evalImpl(nodes.back(), env); } +ASTNodePtr Eval::evalIf(const std::list& 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::Nil); + + auto first_evaluated = evalImpl(first_argument, env); + if (!is(first_evaluated.get()) + || std::static_pointer_cast(first_evaluated)->state() == Value::True) { + return evalImpl(second_argument, env); + } + else { + return evalImpl(third_argument, env); + } +} + ASTNodePtr Eval::apply(std::shared_ptr evaluated_list) { if (evaluated_list == nullptr) { diff --git a/src/eval.h b/src/eval.h index 64a3ee7..9fd85cf 100644 --- a/src/eval.h +++ b/src/eval.h @@ -28,6 +28,7 @@ private: ASTNodePtr evalDef(const std::list& nodes, EnvironmentPtr env); ASTNodePtr evalLet(const std::list& nodes, EnvironmentPtr env); ASTNodePtr evalDo(const std::list& nodes, EnvironmentPtr env); + ASTNodePtr evalIf(const std::list& nodes, EnvironmentPtr env); ASTNodePtr apply(std::shared_ptr evaluated_list); ASTNodePtr m_ast;