Browse Source

Eval: Allow multiple s-expr in try*

master
Riyyi 1 year ago
parent
commit
c6c6d69e73
  1. 56
      src/eval-special-form.cpp

56
src/eval-special-form.cpp

@ -7,6 +7,7 @@
#include <iterator> // std::next, std::prev
#include <list>
#include <memory>
#include <span>
#include <string>
#include "ast.h"
@ -106,41 +107,56 @@ ValuePtr Eval::evalQuote(const ValueVector& nodes)
return nodes.front();
}
// (try* x (catch* y z))
// (try* x ... (catch* y z))
ValuePtr Eval::evalTry(const ValueVector& nodes, EnvironmentPtr env)
{
CHECK_ARG_COUNT_AT_LEAST("try*", nodes.size(), 1);
// Try 'x'
m_ast = nodes.front();
m_env = env;
auto result = evalImpl();
// Is last node a catch* block
bool is_last_node_catch = false;
std::span<const ValuePtr> catch_nodes;
if (nodes.size() >= 2 && is<List>(nodes.back().get())) {
VALUE_CAST(list, List, nodes.back());
catch_nodes = list->nodesRead();
if (!list->empty() && is<Symbol>(catch_nodes.front().get())) {
VALUE_CAST(catch_symbol, Symbol, catch_nodes.front());
if (catch_symbol->symbol() == "catch*") {
CHECK_ARG_COUNT_IS("catch*", catch_nodes.size() - 1, 2);
is_last_node_catch = true;
}
}
}
// Dont have to eval on malformed (catch*)
if (Error::the().hasAnyError()) {
return nullptr;
}
// Try
ValuePtr result;
auto end = (!is_last_node_catch) ? nodes.end() : std::prev(nodes.end(), 1);
for (auto it = nodes.begin(); it != end; ++it) {
m_ast = *it;
m_env = env;
result = evalImpl();
}
if (!Error::the().hasAnyError()) {
return result;
}
if (nodes.size() == 1) {
return nullptr;
}
// Catch
if (!is_last_node_catch) {
return nullptr;
}
// Get the error message
auto error = (Error::the().hasOtherError())
? makePtr<String>(Error::the().otherError())
: Error::the().exception();
Error::the().clearErrors();
VALUE_CAST(catch_list, List, nodes.back());
const auto& catch_nodes = catch_list->nodesRead();
CHECK_ARG_COUNT_IS("catch*", catch_nodes.size() - 1, 2);
VALUE_CAST(catch_symbol, Symbol, catch_nodes.front());
if (catch_symbol->symbol() != "catch*") {
Error::the().add("catch block must begin with catch*");
return nullptr;
}
VALUE_CAST(catch_binding, Symbol, (*std::next(catch_nodes.begin())));
// Create new Environment that binds 'y' to the value of the exception
@ -383,8 +399,6 @@ void Eval::evalWhile(const ValueVector& nodes, EnvironmentPtr env)
// Condition
ValuePtr predicate = *nodes.begin();
// Printer p;
m_ast = predicate;
m_env = env;
ValuePtr condition = evalImpl();
@ -399,8 +413,6 @@ void Eval::evalWhile(const ValueVector& nodes, EnvironmentPtr env)
m_ast = predicate;
m_env = env;
condition = evalImpl();
// print("{}\n", p.print(condition));
}
m_ast = makePtr<Constant>();

Loading…
Cancel
Save