diff --git a/src/eval.cpp b/src/eval.cpp index 6ebf210..84e4943 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -39,6 +39,10 @@ ValuePtr Eval::evalImpl() ValuePtr ast = nullptr; EnvironmentPtr env = nullptr; + if (env == nullptr) { + env = m_outer_env; + } + while (true) { if (Error::the().hasAnyError()) { return nullptr; @@ -47,18 +51,17 @@ ValuePtr Eval::evalImpl() ast = m_ast; env = m_env; - if (env == nullptr) { - env = m_outer_env; + if (is(ast.get())) { + return evalSymbol(ast, env); } - - if (!is(ast.get())) { - return evalAst(ast, env); + if (is(ast.get())) { + return evalVector(ast, env); + } + if (is(ast.get())) { + return evalHashMap(ast, env); } - - ast = macroExpand(ast, env); - if (!is(ast.get())) { - return evalAst(ast, env); + return ast; } auto list = std::static_pointer_cast(ast); @@ -115,80 +118,86 @@ ValuePtr Eval::evalImpl() } } - auto evaluated_list = std::static_pointer_cast(evalAst(ast, env)); + m_ast = list->front(); + m_env = env; + auto evaluated_front = evalImpl(); + auto unevaluated_nodes = list->rest(); - if (evaluated_list == nullptr) { - return nullptr; + if (is(evaluated_front.get())) { // FIXME + auto lambda = std::static_pointer_cast(evaluated_front); + m_ast = lambda->body(); + m_env = Environment::create(lambda, std::move(unevaluated_nodes)); + m_ast = evalImpl(); + m_env = env; + continue; // TCO + } + + ValueVector evaluated_nodes(unevaluated_nodes.size()); + for (size_t i = 0; i < unevaluated_nodes.size(); ++i) { + m_ast = unevaluated_nodes[i]; + m_env = env; + evaluated_nodes[i] = evalImpl(); } // Regular list - if (is(evaluated_list->front().get())) { - auto lambda = std::static_pointer_cast(evaluated_list->front()); + if (is(evaluated_front.get())) { + auto lambda = std::static_pointer_cast(evaluated_front); m_ast = lambda->body(); - m_env = Environment::create(lambda, evaluated_list->rest()); + m_env = Environment::create(lambda, std::move(evaluated_nodes)); continue; // TCO } // Function call - return apply(evaluated_list); + return apply(evaluated_front, evaluated_nodes); } } -ValuePtr Eval::evalAst(ValuePtr ast, EnvironmentPtr env) +ValuePtr Eval::evalSymbol(ValuePtr ast, EnvironmentPtr env) { - if (ast == nullptr || env == nullptr) { + auto result = env->get(std::static_pointer_cast(ast)->symbol()); + if (!result) { + Error::the().add(::format("'{}' not found", ast)); return nullptr; } - Value* ast_raw_ptr = ast.get(); - if (is(ast_raw_ptr)) { - auto result = env->get(std::static_pointer_cast(ast)->symbol()); - if (!result) { - Error::the().add(::format("'{}' not found", ast)); + return result; +} + +ValuePtr Eval::evalVector(ValuePtr ast, EnvironmentPtr env) +{ + const auto& nodes = std::static_pointer_cast(ast)->nodesRead(); + size_t count = nodes.size(); + auto evaluated_nodes = ValueVector(count); + + for (size_t i = 0; i < count; ++i) { + m_ast = nodes[i]; + m_env = env; + ValuePtr eval_node = evalImpl(); + if (eval_node == nullptr) { return nullptr; } - - return result; + evaluated_nodes.at(i) = eval_node; } - else if (is(ast_raw_ptr)) { - const auto& nodes = std::static_pointer_cast(ast)->nodesRead(); - size_t count = nodes.size(); - auto evaluated_nodes = ValueVector(count); - - for (size_t i = 0; i < count; ++i) { - m_ast = nodes[i]; - m_env = env; - ValuePtr eval_node = evalImpl(); - if (eval_node == nullptr) { - return nullptr; - } - evaluated_nodes.at(i) = eval_node; - } - if (is(ast_raw_ptr)) { - return makePtr(evaluated_nodes); - } + return makePtr(evaluated_nodes); +} - return makePtr(evaluated_nodes); - } - else if (is(ast_raw_ptr)) { - const auto& elements = std::static_pointer_cast(ast)->elements(); - Elements evaluated_elements; - for (const auto& element : elements) { - m_ast = element.second; - m_env = env; - ValuePtr element_node = evalImpl(); - if (element_node == nullptr) { - return nullptr; - } - evaluated_elements.insert_or_assign(element.first, element_node); +ValuePtr Eval::evalHashMap(ValuePtr ast, EnvironmentPtr env) +{ + const auto& elements = std::static_pointer_cast(ast)->elements(); + Elements evaluated_elements; + for (const auto& element : elements) { + m_ast = element.second; + m_env = env; + ValuePtr element_node = evalImpl(); + if (element_node == nullptr) { + return nullptr; } - - return makePtr(evaluated_elements); + evaluated_elements.insert_or_assign(element.first, element_node); } - return ast; + return makePtr(evaluated_elements); } // ----------------------------------------- @@ -237,22 +246,16 @@ ValuePtr Eval::macroExpand(ValuePtr ast, EnvironmentPtr env) // ----------------------------------------- -ValuePtr Eval::apply(std::shared_ptr evaluated_list) +ValuePtr Eval::apply(ValuePtr function, const ValueVector& nodes) { - if (evaluated_list == nullptr) { - return nullptr; - } - - auto front = evaluated_list->front(); - - if (!is(front.get())) { - Error::the().add(::format("invalid function: {}", front)); + if (!is(function.get())) { + Error::the().add(::format("invalid function: {}", function)); return nullptr; } - auto function = std::static_pointer_cast(front)->function(); + auto func = std::static_pointer_cast(function)->function(); - return function(evaluated_list->begin() + 1, evaluated_list->end()); + return func(nodes.begin(), nodes.end()); } } // namespace blaze diff --git a/src/eval.h b/src/eval.h index 205d630..b6cd48e 100644 --- a/src/eval.h +++ b/src/eval.h @@ -27,7 +27,9 @@ public: private: ValuePtr evalImpl(); - ValuePtr evalAst(ValuePtr ast, EnvironmentPtr env); + ValuePtr evalSymbol(ValuePtr ast, EnvironmentPtr env); + ValuePtr evalVector(ValuePtr ast, EnvironmentPtr env); + ValuePtr evalHashMap(ValuePtr ast, EnvironmentPtr env); bool isMacroCall(ValuePtr ast, EnvironmentPtr env); ValuePtr macroExpand(ValuePtr ast, EnvironmentPtr env); @@ -46,7 +48,7 @@ private: void evalQuasiQuote(const ValueVector& nodes, EnvironmentPtr env); void evalWhile(const ValueVector& nodes, EnvironmentPtr env); - ValuePtr apply(std::shared_ptr evaluated_list); + ValuePtr apply(ValuePtr function, const ValueVector& nodes); ValuePtr m_ast; EnvironmentPtr m_env;