|
|
@ -4,10 +4,13 @@ |
|
|
|
* SPDX-License-Identifier: MIT |
|
|
|
* SPDX-License-Identifier: MIT |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <iterator> // std::next, std::prev |
|
|
|
#include <list> |
|
|
|
#include <list> |
|
|
|
#include <memory> |
|
|
|
#include <memory> |
|
|
|
|
|
|
|
#include <string> |
|
|
|
|
|
|
|
|
|
|
|
#include "ast.h" |
|
|
|
#include "ast.h" |
|
|
|
|
|
|
|
#include "environment.h" |
|
|
|
#include "error.h" |
|
|
|
#include "error.h" |
|
|
|
#include "eval.h" |
|
|
|
#include "eval.h" |
|
|
|
#include "forward.h" |
|
|
|
#include "forward.h" |
|
|
@ -277,6 +280,51 @@ void Eval::evalQuasiQuote(const std::list<ValuePtr>& nodes, EnvironmentPtr env) |
|
|
|
return; // TCO
|
|
|
|
return; // TCO
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// (try* x (catch* y z))
|
|
|
|
|
|
|
|
void Eval::evalTry(const std::list<ValuePtr>& nodes, EnvironmentPtr env) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CHECK_ARG_COUNT_AT_LEAST("try*", nodes.size(), 1, void()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Try 'x'
|
|
|
|
|
|
|
|
m_ast_stack.push(nodes.front()); |
|
|
|
|
|
|
|
m_env_stack.push(env); |
|
|
|
|
|
|
|
auto result = evalImpl(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Catch
|
|
|
|
|
|
|
|
if (nodes.size() == 2 && (Error::the().hasOtherError() || Error::the().hasException())) { |
|
|
|
|
|
|
|
// Get the exception
|
|
|
|
|
|
|
|
auto error = (Error::the().hasOtherError()) |
|
|
|
|
|
|
|
? makePtr<String>(Error::the().otherError()) |
|
|
|
|
|
|
|
: Error::the().exception(); |
|
|
|
|
|
|
|
Error::the().clearErrors(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VALUE_CAST(catch_list, List, nodes.back(), void()); |
|
|
|
|
|
|
|
auto catch_nodes = catch_list->nodes(); |
|
|
|
|
|
|
|
CHECK_ARG_COUNT_IS("catch*", catch_nodes.size() - 1, 2, void()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VALUE_CAST(catch_symbol, Symbol, catch_nodes.front(), void()); |
|
|
|
|
|
|
|
if (catch_symbol->symbol() != "catch*") { |
|
|
|
|
|
|
|
Error::the().add("catch block must begin with catch*"); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VALUE_CAST(catch_binding, Symbol, (*std::next(catch_nodes.begin())), void()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create new Environment that binds 'y' to the value of the exception
|
|
|
|
|
|
|
|
auto catch_env = Environment::create(env); |
|
|
|
|
|
|
|
catch_env->set(catch_binding->symbol(), error); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Evaluate 'z' using the new Environment
|
|
|
|
|
|
|
|
m_ast_stack.push(catch_nodes.back()); |
|
|
|
|
|
|
|
m_env_stack.push(catch_env); |
|
|
|
|
|
|
|
return; // TCO
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_ast_stack.push(result); |
|
|
|
|
|
|
|
m_env_stack.push(env); |
|
|
|
|
|
|
|
return; // TCO
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------
|
|
|
|
// -----------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace blaze
|
|
|
|
} // namespace blaze
|
|
|
|