#ifndef TEMPLATE_VECTOR_TEST_INTERPRETER_HPP
#define TEMPLATE_VECTOR_TEST_INTERPRETER_HPP
#include "natch.hpp"
#include "$$NATCH:cprog14simplecontainer/test/interpreter.hpp"
#include <cstddef>
#include <initializer_list>
#include <stdexcept>
#include <utility>
#include <iterator>
#include <memory>
template<class T>
class template_container_test_interpreter;
template<template<class...> class Container, class T>
class template_container_test_interpreter<Container<T>>
: public simple_container_test_interpreter<Container<T>>
{
public:
using element_type = T;
using environment_type = natch::environment<Container<T>>;
using var = typename environment_type::variable_type;
using _base = simple_container_test_interpreter<Container<T>>;
template_container_test_interpreter (natch::basic_environment const& be)
: _base (be)
{
register_instruction ("construct", +[](var& data) {
data.construct ();
});
register_instruction ("destruct", +[](var& data) {
data.destruct ();
});
register_instruction ("size_value_init", +[](var& dst, std::size_t size, element_type const& data) {
dst.construct (size, data);
});
register_instruction ("push_back", +[](var& dst, element_type const& val) {
dst->push_back (val);
});
register_instruction ("erase", +[](var& dst, std::size_t idx, environment_type& env) {
try {
dst->erase (idx);
} catch (std::out_of_range const& e) { env.output ("std::out_of_range"); }
catch (...) { env.output ("unknown-exception");
}
});
register_instruction ("clear", +[](var& dst) {
dst->clear ();
});
register_instruction ("insert", +[](var& dst, std::size_t idx, element_type const& val, environment_type& env) {
try {
dst->insert (idx, val);
} catch (std::out_of_range const& e) { env.output ("std::out_of_range"); }
catch (...) { env.output ("unknown-exception");
}
});
register_instruction ("read_end-1", +[](var& dst, environment_type& env) {
if (dst->size () > 0) env.output ("val: ", *(dst->end ()-1));
else env.output ("vector is empty");
});
register_instruction ("read_begin", +[](var& dst, environment_type& env) {
if (dst->size () > 0) env.output ("val: ", *(dst->begin ()));
else env.output ("vector is empty");
});
register_instruction ("assert_greater_capacity", +[](var const& dst, std::size_t mini_cap, environment_type& env) {
if (dst)
env.output ("capacity > ", mini_cap, " =>", dst->capacity () > mini_cap);
else
env.output ("uninitialized target");
});
register_instruction ("find", +[](var const& dst, element_type const& needle, environment_type& env) {
if (dst)
env.output ("idx: ", std::distance (dst->begin (), dst->find (needle)));
else
env.output ("uninitialized target");
});
register_instruction ("reset", +[](var& lhs) {
auto prev_capacity = lhs->capacity ();
auto prev_size = lhs->size ();
lhs->reset ();
if (prev_capacity != lhs->capacity () || prev_size != lhs->size ())
throw natch::logic_error ("vec.reset () shall not modify `size ()` or `capacity ()`");
});
}
protected:
template<class F>
void register_instruction (std::string const& key, F&& f)
{
this->_base::register_instruction (key, std::forward<F> (f));
}
};
#endif