Program Listing for File OpLookup.hpp

Return to documentation for file (include/sgpl/library/OpLookup.hpp)

#pragma once
#ifndef SGPL_LIBRARY_OPLOOKUP_HPP_INCLUDE
#define SGPL_LIBRARY_OPLOOKUP_HPP_INCLUDE

#include <cassert>
#include <unordered_map>

#include "../../../third-party/conduit/include/uitsl/meta/tuple_has_type.hpp"
#include "../../../third-party/conduit/include/uitsl/meta/tuple_index.hpp"
#include "../../../third-party/conduit/include/uit_emp/base/macros.hpp"

#include "../debug/sgpl_assert.hpp"
#include "../debug/sgpl_error.hpp"
#include "../operations/actions/Nop.hpp"
#include "../utility/ByteEnumeration.hpp"
#include "../utility/count_operation_random_touches.hpp"

namespace sgpl {
#include "../../../third-party/conduit/include/uit_emp/vendorization/push_macros.hh"

template<typename Library>
class OpLookup {

  std::unordered_map<std::string, unsigned char> table;

  using library_parent_t = typename Library::parent_t;

public:

  OpLookup() {

    #define SGPL_OP_LOOKUP_PAYLOAD(N) \
      if constexpr (N < Library::GetSize()) { \
        using Operation = typename Library::template Operation<N>; \
        table[ Operation::name() ] = N; \
      } \

    static_assert( Library::GetSize() < 256 );

    EMP_WRAP_EACH( SGPL_OP_LOOKUP_PAYLOAD, SGPL_BYTE_ENUMERATION )

    sgpl_assert(
      table.size() == Library::GetSize(),
      table.size() << Library::GetSize()
    );

  }

  unsigned char GetOpCode(const std::string op_name) const {
    return table.at(op_name);
  }

  static std::string GetOpName(const size_t op_code) {

    // can't use assert due to obsucre macro error
    #define SGPL_OP_NAME_PAYLOAD(N) \
      case N: \
        if constexpr (N < Library::GetSize()) { \
          using Operation = typename Library::template Operation<N>; \
          return Operation::name(); \
        } else { \
          assert( false && N ); \
          __builtin_unreachable(); \
        } \
      break;

    static_assert( Library::GetSize() < 256 );

    switch( op_code ) {

      EMP_WRAP_EACH( SGPL_OP_NAME_PAYLOAD, SGPL_BYTE_ENUMERATION )

      default:
        sgpl_assert( false, op_code );
        __builtin_unreachable();

    }

    sgpl_error(op_code);
    __builtin_unreachable();

  }

  template< typename Spec >
  static size_t GetOpNumRngTouches(const size_t op_code) {

    #define SGPL_OP_NUM_RNG_TOUCHES_PAYLOAD(N) \
      case N: \
        if constexpr (N < Library::GetSize()) { \
          using Operation = typename Library::template Operation<N>; \
          return sgpl::count_operation_random_touches< Operation, Spec >(); \
        } else { \
          assert( false && N ); \
          __builtin_unreachable(); \
        } \
      break;

    static_assert( Library::GetSize() < 256 );

    switch( op_code ) {

      EMP_WRAP_EACH( SGPL_OP_NUM_RNG_TOUCHES_PAYLOAD, SGPL_BYTE_ENUMERATION )

      default:
        sgpl_error(op_code);
        __builtin_unreachable();

    }

    sgpl_error(op_code);
    __builtin_unreachable();

  }

  static size_t GetNopOpCode( const size_t num_rng_touches ) {

    #define SGPL_NOP_OP_CODE_PAYLOAD(N) \
      case N: \
        if constexpr ( \
          uitsl::tuple_has_type< sgpl::Nop<N>, library_parent_t >::value \
        )  return uitsl::tuple_index< sgpl::Nop<N>, library_parent_t >::value; \
        else if constexpr ( \
          uitsl::tuple_has_type< sgpl::Nop<N, 0>, library_parent_t >::value \
        )  return uitsl::tuple_index<sgpl::Nop<N, 0>, library_parent_t>::value; \
        else { \
          assert( false && N ); \
          __builtin_unreachable(); \
        } \
      break;

    assert( num_rng_touches < 256 );

    switch( num_rng_touches ) {

      EMP_WRAP_EACH( SGPL_NOP_OP_CODE_PAYLOAD, SGPL_BYTE_ENUMERATION )

      default:
        sgpl_error(num_rng_touches);
        __builtin_unreachable();

    }

    sgpl_error(num_rng_touches);
    __builtin_unreachable();

  }

  static size_t GetOpPrevalence(const size_t op_code) {

    #define SGPL_OP_PREVALENCE_PAYLOAD(N) \
      case N: \
        if constexpr (N < Library::GetSize()) { \
          using Operation = typename Library::template Operation<N>; \
          return Operation::prevalence(); \
        } else { \
          assert( false && N ); \
          __builtin_unreachable(); \
        } \
      break;

    static_assert( Library::GetSize() < 256 );

    switch( op_code ) {

      EMP_WRAP_EACH( SGPL_OP_PREVALENCE_PAYLOAD, SGPL_BYTE_ENUMERATION )

      default:
        sgpl_error(op_code);
        __builtin_unreachable();

    }

    sgpl_error(op_code);
    __builtin_unreachable();

  }

  template< typename Instruction >
  static auto GetOpDescriptors(
    const size_t op_code, const Instruction& instruction
  ) {

    #define SGPL_OP_GET_DESCRIPTORS(N) \
      case N: \
        if constexpr (N < Library::GetSize()) { \
          using Operation = typename Library::template Operation<N>; \
          return Operation::descriptors( instruction ); \
        } else { \
          assert( false && N ); \
          __builtin_unreachable(); \
        } \
      break;

    static_assert( Library::GetSize() < 256 );

    switch( op_code ) {

      EMP_WRAP_EACH(
        SGPL_OP_GET_DESCRIPTORS, SGPL_BYTE_ENUMERATION
      )

      default:
        sgpl_error(op_code);
        __builtin_unreachable();

    }

    sgpl_error(op_code);
    __builtin_unreachable();

  }

  template< typename Instruction >
  static auto GetOpCategories(
    const size_t op_code, const Instruction& instruction
  ) {

    // can't use sgpl_assert due to obsucre macro error
    #define SGPL_OP_GET_CATEGORIES(N) \
      case N: \
        if constexpr (N < Library::GetSize()) { \
          using Operation = typename Library::template Operation<N>; \
          return Operation::categories( instruction ); \
        } else { \
          assert( false && N ); \
          __builtin_unreachable(); \
        } \
      break;

    static_assert( Library::GetSize() < 256 );

    switch( op_code ) {

      EMP_WRAP_EACH(
        SGPL_OP_GET_CATEGORIES, SGPL_BYTE_ENUMERATION
      )

      default:
        sgpl_error(op_code);
        __builtin_unreachable();

    }

    sgpl_error(op_code);
    __builtin_unreachable();

  }

};

#include "../../../third-party/conduit/include/uit_emp/vendorization/pop_macros.hh"
} // namespace sgpl

#endif // #ifndef SGPL_LIBRARY_OPLOOKUP_HPP_INCLUDE