begin program

thread
Brett 2024-06-19 14:12:04 -04:00
parent b8268467da
commit ac36a63c5b
6 changed files with 322 additions and 279 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.20) project(blt-gp VERSION 0.0.21)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

View File

@ -24,252 +24,252 @@
#include <random> #include <random>
//// small scale //// small scale
//enum class op enum class op
//{ {
// ADD, ADD,
// SUB, SUB,
// MUL, MUL,
// DIV, DIV,
// LIT LIT
//}; };
//
//std::string to_string(op o) std::string to_string(op o)
//{ {
// switch (o) switch (o)
// { {
// case op::ADD: case op::ADD:
// return "ADD"; return "ADD";
// case op::SUB: case op::SUB:
// return "SUB"; return "SUB";
// case op::MUL: case op::MUL:
// return "MUL"; return "MUL";
// case op::DIV: case op::DIV:
// return "DIV"; return "DIV";
// case op::LIT: case op::LIT:
// return "LIT"; return "LIT";
// } }
// return ""; return "";
//} }
//
//constexpr static long SEED = 41912; constexpr static long SEED = 41912;
//
//op generate_op() op generate_op()
//{ {
// static std::mt19937_64 engine(SEED); static std::mt19937_64 engine(SEED);
// static std::uniform_int_distribution dist(0, static_cast<int>(op::LIT) - 1); static std::uniform_int_distribution dist(0, static_cast<int>(op::LIT) - 1);
// return static_cast<op>(dist(engine)); return static_cast<op>(dist(engine));
//} }
//
//bool choice() bool choice()
//{ {
// static std::mt19937_64 engine(SEED); static std::mt19937_64 engine(SEED);
// static std::uniform_int_distribution dist(0, 1); static std::uniform_int_distribution dist(0, 1);
// return dist(engine); return dist(engine);
//} }
//
//float random_value() float random_value()
//{ {
// static std::mt19937_64 engine(SEED); static std::mt19937_64 engine(SEED);
// static std::uniform_real_distribution dist(0.0f, 10.0f); static std::uniform_real_distribution dist(0.0f, 10.0f);
// return dist(engine); return dist(engine);
//} }
//
//void test() void test()
//{ {
// std::vector<op> operations; std::vector<op> operations;
// std::vector<float> values; std::vector<float> values;
//
// std::stack<op> tree_generator; std::stack<op> tree_generator;
// tree_generator.push(generate_op()); tree_generator.push(generate_op());
//
// while (!tree_generator.empty()) while (!tree_generator.empty())
// { {
// auto opn = tree_generator.top(); auto opn = tree_generator.top();
// tree_generator.pop(); tree_generator.pop();
//
// operations.push_back(opn); operations.push_back(opn);
// if (opn == op::LIT) if (opn == op::LIT)
// { {
// values.push_back(random_value()); values.push_back(random_value());
// continue; continue;
// } }
//
// // child 1 // child 1
// if (choice()) if (choice())
// tree_generator.push(generate_op()); tree_generator.push(generate_op());
// else else
// tree_generator.push(op::LIT); tree_generator.push(op::LIT);
//
// // child 2 // child 2
// if (choice()) if (choice())
// tree_generator.push(generate_op()); tree_generator.push(generate_op());
// else else
// tree_generator.push(op::LIT); tree_generator.push(op::LIT);
// } }
//
// for (const auto& v : operations) for (const auto& v : operations)
// std::cout << to_string(v) << " "; std::cout << to_string(v) << " ";
// std::cout << std::endl; std::cout << std::endl;
//
// { {
// std::stack<blt::size_t> process; std::stack<blt::size_t> process;
// for (const auto& v : operations) for (const auto& v : operations)
// { {
// switch (v) switch (v)
// { {
// case op::ADD: case op::ADD:
// case op::SUB: case op::SUB:
// case op::MUL: case op::MUL:
// case op::DIV: case op::DIV:
// process.emplace(2); process.emplace(2);
// std::cout << "("; std::cout << "(";
// break; break;
// case op::LIT: case op::LIT:
// break; break;
// } }
// std::cout << to_string(v); std::cout << to_string(v);
// while (!process.empty()) while (!process.empty())
// { {
// auto top = process.top(); auto top = process.top();
// process.pop(); process.pop();
// if (top == 0) if (top == 0)
// { {
// std::cout << ")"; std::cout << ")";
// continue; continue;
// } else } else
// { {
// std::cout << " "; std::cout << " ";
// process.push(top - 1); process.push(top - 1);
// break; break;
// } }
// } }
// } }
// while (!process.empty()) while (!process.empty())
// { {
// auto top = process.top(); auto top = process.top();
// process.pop(); process.pop();
// if (top == 0) if (top == 0)
// { {
// std::cout << ") "; std::cout << ") ";
// continue; continue;
// } else } else
// { {
// std::cerr << "FUCK YOU\n"; std::cerr << "FUCK YOU\n";
// break; break;
// } }
// } }
// std::cout << std::endl; std::cout << std::endl;
// } }
//
// for (const auto& v : values) for (const auto& v : values)
// std::cout << v << " "; std::cout << v << " ";
// std::cout << std::endl; std::cout << std::endl;
//
// { {
// std::stack<blt::size_t> process; std::stack<blt::size_t> process;
// blt::size_t index = 0; blt::size_t index = 0;
// for (const auto& v : operations) for (const auto& v : operations)
// { {
// switch (v) switch (v)
// { {
// case op::ADD: case op::ADD:
// case op::SUB: case op::SUB:
// case op::MUL: case op::MUL:
// case op::DIV: case op::DIV:
// process.emplace(2); process.emplace(2);
// std::cout << "("; std::cout << "(";
// std::cout << to_string(v); std::cout << to_string(v);
// break; break;
// case op::LIT: case op::LIT:
// std::cout << values[index++]; std::cout << values[index++];
// break; break;
// } }
//
// while (!process.empty()) while (!process.empty())
// { {
// auto top = process.top(); auto top = process.top();
// process.pop(); process.pop();
// if (top == 0) if (top == 0)
// { {
// std::cout << ")"; std::cout << ")";
// continue; continue;
// } else } else
// { {
// std::cout << " "; std::cout << " ";
// process.push(top - 1); process.push(top - 1);
// break; break;
// } }
// } }
// } }
// while (!process.empty()) while (!process.empty())
// { {
// auto top = process.top(); auto top = process.top();
// process.pop(); process.pop();
// if (top == 0) if (top == 0)
// { {
// std::cout << ") "; std::cout << ") ";
// continue; continue;
// } else } else
// { {
// std::cerr << "FUCK YOU\n"; std::cerr << "FUCK YOU\n";
// break; break;
// } }
// } }
// std::cout << std::endl; std::cout << std::endl;
// } }
//
// std::stack<float> process; std::stack<float> process;
// std::stack<op> operators; std::stack<op> operators;
//
// for (const auto& v : operations) for (const auto& v : operations)
// operators.push(v); operators.push(v);
//
// while (!operators.empty()) while (!operators.empty())
// { {
// auto oper = operators.top(); auto oper = operators.top();
// operators.pop(); operators.pop();
// if (oper == op::LIT) if (oper == op::LIT)
// { {
// process.push(values.back()); process.push(values.back());
// values.pop_back(); values.pop_back();
// } else } else
// { {
// auto v1 = process.top(); auto v1 = process.top();
// process.pop(); process.pop();
// auto v2 = process.top(); auto v2 = process.top();
// process.pop(); process.pop();
// std::cout << "processing oper " << to_string(oper) << " with values " << v1 << " " << v2 << std::endl; std::cout << "processing oper " << to_string(oper) << " with values " << v1 << " " << v2 << std::endl;
// switch (oper) switch (oper)
// { {
// case op::ADD: case op::ADD:
// values.push_back(v1 + v2); values.push_back(v1 + v2);
// operators.push(op::LIT); operators.push(op::LIT);
// break; break;
// case op::SUB: case op::SUB:
// values.push_back(v1 - v2); values.push_back(v1 - v2);
// operators.push(op::LIT); operators.push(op::LIT);
// break; break;
// case op::MUL: case op::MUL:
// values.push_back(v1 * v2); values.push_back(v1 * v2);
// operators.push(op::LIT); operators.push(op::LIT);
// break; break;
// case op::DIV: case op::DIV:
// if (v2 == 0) if (v2 == 0)
// v2 = 1; v2 = 1;
// values.push_back(v1 / v2); values.push_back(v1 / v2);
// operators.push(op::LIT); operators.push(op::LIT);
// break; break;
// case op::LIT: case op::LIT:
// break; break;
// } }
// std::cout << "\tresult: " << values.back() << std::endl; std::cout << "\tresult: " << values.back() << std::endl;
// } }
// } }
//
// std::cout << process.size() << std::endl; std::cout << process.size() << std::endl;
// std::cout << process.top() << std::endl; std::cout << process.top() << std::endl;
//
//} }
// //
//struct silly //struct silly
//{ //{
@ -368,12 +368,12 @@ int main()
alloc.push(120); alloc.push(120);
alloc.push(true); alloc.push(true);
blt::gp::operation<float(float, int, bool)> silly_op(nyah); blt::gp::operation_t<float(float, int, bool)> silly_op(nyah);
blt::gp::operation<float(float,float)> silly_op_2([](float f, float g) { blt::gp::operation_t<float(float, float)> silly_op_2([](float f, float g) {
return f + g; return f + g;
}); });
std::cout << silly_op_2(alloc) << std::endl; std::cout << silly_op(alloc) << std::endl;
std::cout << "Is empty? " << alloc.empty() << std::endl; std::cout << "Is empty? " << alloc.empty() << std::endl;

View File

@ -21,7 +21,7 @@
namespace blt::gp namespace blt::gp
{ {
class identifier;
} }
#endif //BLT_GP_FWDECL_H #endif //BLT_GP_FWDECL_H

View File

@ -24,6 +24,7 @@
#include <blt/gp/fwdecl.h> #include <blt/gp/fwdecl.h>
#include <functional> #include <functional>
#include <blt/std/ranges.h> #include <blt/std/ranges.h>
#include <blt/std/hashmap.h>
#include <blt/std/types.h> #include <blt/std/types.h>
#include <blt/std/utility.h> #include <blt/std/utility.h>
#include <type_traits> #include <type_traits>
@ -34,9 +35,6 @@
namespace blt::gp namespace blt::gp
{ {
class identifier
{
};
class type class type
{ {
@ -79,33 +77,39 @@ namespace blt::gp
template<typename T> template<typename T>
inline type register_type() inline type register_type()
{ {
types.push_back(type::make_type<T>(types.size())); types[blt::type_string_raw<T>()](type::make_type<T>(types.size()));
return types.back(); return types[blt::type_string_raw<T>()];
}
template<typename T>
inline type get_type()
{
return types[blt::type_string_raw<T>()];
} }
private: private:
std::vector<type> types; blt::hashmap_t<std::string, type> types;
}; };
template<typename Signature> template<typename Signature>
class operation; class operation_t;
template<typename Return, typename... Args> template<typename Return, typename... Args>
class operation<Return(Args...)> class operation_t<Return(Args...)>
{ {
public: public:
using function_t = std::function<Return(Args...)>; using function_t = std::function<Return(Args...)>;
constexpr operation(const operation& copy) = default; constexpr operation_t(const operation_t& copy) = default;
constexpr operation(operation&& move) = default; constexpr operation_t(operation_t&& move) = default;
template<typename Functor> template<typename Functor>
constexpr explicit operation(const Functor& functor): func(functor) constexpr explicit operation_t(const Functor& functor): func(functor)
{} {}
template<blt::u64 index> template<blt::u64 index>
[[nodiscard]] inline constexpr blt::size_t getByteOffset() const [[nodiscard]] inline constexpr static blt::size_t getByteOffset()
{ {
blt::size_t offset = 0; blt::size_t offset = 0;
blt::size_t current_index = 0; blt::size_t current_index = 0;
@ -114,7 +118,7 @@ namespace blt::gp
} }
template<blt::u64... indices> template<blt::u64... indices>
inline constexpr Return sequence_to_indices(stack_allocator& allocator, std::integer_sequence<blt::u64, indices...>) const inline constexpr Return exec_sequence_to_indices(stack_allocator& allocator, std::integer_sequence<blt::u64, indices...>) const
{ {
// expands Args and indices, providing each argument with its index calculating the current argument byte offset // expands Args and indices, providing each argument with its index calculating the current argument byte offset
return func(allocator.from<Args>(getByteOffset<indices>())...); return func(allocator.from<Args>(getByteOffset<indices>())...);
@ -123,29 +127,30 @@ namespace blt::gp
[[nodiscard]] constexpr inline Return operator()(stack_allocator& allocator) const [[nodiscard]] constexpr inline Return operator()(stack_allocator& allocator) const
{ {
constexpr auto seq = std::make_integer_sequence<blt::u64, sizeof...(Args)>(); constexpr auto seq = std::make_integer_sequence<blt::u64, sizeof...(Args)>();
Return ret = sequence_to_indices(allocator, seq); Return ret = exec_sequence_to_indices(allocator, seq);
allocator.call_destructors<Args...>();
allocator.pop_bytes((stack_allocator::aligned_size<Args>() + ...)); allocator.pop_bytes((stack_allocator::aligned_size<Args>() + ...));
return ret; return ret;
} }
private: [[nodiscard]] std::function<void(stack_allocator&)> make_callable() const
// template<typename T, blt::size_t index> {
// static inline T& access_pack_index(blt::span<void*> args) return [this](stack_allocator& values) {
// { values.push(this->operator()(values));
// return *reinterpret_cast<T*>(args[index]); };
// } }
//
// template<typename T, T... indexes>
// Return function_evaluator(blt::span<void*> args, std::integer_sequence<T, indexes...>)
// {
// return func(access_pack_index<Args, indexes>(args)...);
// }
[[nodiscard]] blt::size_t get_argc() const
{
return sizeof...(Args);
}
private:
function_t func; function_t func;
}; };
template<typename Return, typename... Args> template<typename Return, typename... Args>
operation(Return (*)(Args...)) -> operation<Return(Args...)>; operation_t(Return (*)(Args...)) -> operation_t<Return(Args...)>;
// //
// template<typename Sig> // template<typename Sig>
// operation(std::function<Sig>) -> operation<Sig>; // operation(std::function<Sig>) -> operation<Sig>;
@ -153,6 +158,37 @@ namespace blt::gp
// template<typename Return, typename... Args> // template<typename Return, typename... Args>
// operation(std::function<Return(Args...)>) -> operation<Return(Args...)>; // operation(std::function<Return(Args...)>) -> operation<Return(Args...)>;
class gp_program
{
public:
explicit gp_program(type_system system): system(std::move(system))
{}
template<typename Return, typename... Args>
void add_operator(const operation_t<Return(Args...)>& op)
{
if (op.get_argc() == 0)
terminals.push_back(operators.size());
else
non_terminals.push_back(operators.size());
operators.push_back(op.make_callable());
std::vector<type> types;
(types.push_back(system.get_type<Args>()), ...);
arg_types.push_back(std::move(types));
return_types.push_back(system.get_type<Return>());
}
private:
type_system system;
std::vector<std::function<void(stack_allocator&)>> operators;
std::vector<blt::size_t> terminals;
std::vector<blt::size_t> non_terminals;
std::vector<type> return_types;
std::vector<std::vector<type>> arg_types;
};
} }

View File

@ -112,6 +112,13 @@ namespace blt::gp
} }
} }
template<typename... Args>
void call_destructors()
{
blt::size_t offset = 0;
((from<Args>(offset).~Args(), offset += stack_allocator::aligned_size<Args>()), ...);
}
[[nodiscard]] bool empty() const [[nodiscard]] bool empty() const
{ {
if (head == nullptr) if (head == nullptr)

@ -1 +1 @@
Subproject commit 8d3bfbcdc36fb769257ae58c0374ef44253e0a34 Subproject commit 2266d64f042bc97b54e7e50dcaac730bcc3ab4c3