thesis version

This commit is contained in:
2021-05-10 18:14:24 +02:00
commit caf2a692f9
281 changed files with 73182 additions and 0 deletions

19
inc/alsk/edsl/edsl.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef ALSK_ALSK_EDSL_EDSL_H
#define ALSK_ALSK_EDSL_EDSL_H
#include "implement.h"
#include "link.h"
#include "op/op.h"
namespace alsk {
namespace edsl {
template<typename Expression, std::enable_if_t<isOperand<std::decay_t<Expression>>>* = nullptr>
constexpr decltype(auto) seq(Expression&& expression) {
return &std::forward<Expression>(expression);
}
}
}
#endif

50
inc/alsk/edsl/implement.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef ALSK_ALSK_EDSL_IMPL_H
#define ALSK_ALSK_EDSL_IMPL_H
#include <utility>
#include "../executor/traits.h"
#include "../skeleton/utility.h"
#include "../impl/impl.h"
#include "op/impl/serial.h"
#include "op/traits.h"
#include "link.h"
namespace alsk {
namespace edsl {
template<typename Expression>
constexpr auto getSkeleton(Expression) -> BuildSkeletonT<typename Expression::Struct, typename Expression::Links>;
template<
template<typename> class Executor, typename Context = DefaultContext,
typename Expression,
std::enable_if_t<isBranch<std::decay_t<Expression>>>* = nullptr
>
constexpr auto implement(Expression&& expression) {
using Skeleton = decltype(getSkeleton(expression));
auto f = alsk::implement<Executor, Skeleton, Context>();
std::forward<Expression>(expression).setup(f.skeleton);
return f;
}
template<
template<typename> class Executor, typename Context = DefaultContext,
typename Expression,
std::enable_if_t<isLeaf<std::decay_t<Expression>>>* = nullptr
>
constexpr auto implement(Expression&& expression) {
using Signature = typename std::decay_t<Expression>::Signature;
using FixedSignatures = AutoLinkSerial<Signature>;
auto linkedExpression = link<typename FixedSignatures::in>(std::forward<Expression>(expression));
using LinkedExpression = std::decay_t<decltype(linkedExpression)>;
return implement<Executor, Context>(Serial<typename FixedSignatures::out, LinkedExpression>{std::move(linkedExpression)});
}
}
}
#endif

34
inc/alsk/edsl/link.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef ALSK_ALSK_EDSL_LINK_H
#define ALSK_ALSK_EDSL_LINK_H
#include <utility>
#include "op/op.h"
namespace alsk {
namespace edsl {
template<typename Signature, typename Expression>
constexpr decltype(auto) link(Expression&& expression) {
return std::forward<Expression>(expression).template link<Signature>();
}
template<typename Signature, typename... Expressions, std::enable_if_t<(sizeof...(Expressions) > 1)>* = nullptr>
constexpr decltype(auto) link(Expressions&&... expressions) {
return link<Signature>(serial(std::forward<Expressions>(expressions)...));
}
template<typename Signature, typename Type, std::enable_if_t<not isOperand<Type>>* = nullptr>
constexpr decltype(auto) link() {
return link<Signature>(makeOperand<Type>());
}
template<typename Signature, typename Type, std::enable_if_t<isOperand<Type>>* = nullptr>
constexpr decltype(auto) link() {
return link<Signature, Type>();
}
}
}
#endif

View File

@ -0,0 +1,85 @@
#ifndef ALSK_ALSK_EDSL_OP_IMPL_FARM_H
#define ALSK_ALSK_EDSL_OP_IMPL_FARM_H
#include <utility>
#include "../traits.h"
#include "../../../skeleton/bone/farm.h"
#include "../../../skeleton/struct/struct.h"
#include "../../../skeleton/link/link.h"
namespace alsk {
namespace edsl {
template<typename, typename, typename> struct FarmSel;
template<typename Signature_, typename Task>
struct Farm: OperandBase {
Task task;
unsigned int n;
constexpr Farm(Task task, unsigned int n)
noexcept(noexcept(Task{std::move(task)})):
task{std::move(task)}, n{n} {}
template<typename S>
constexpr Farm(Farm<S, Task> const& o)
noexcept(noexcept(Task{o.task})):
task{o.task}, n{o.n} {}
template<typename S>
constexpr Farm(Farm<S, Task>&& o)
noexcept(noexcept(Task{std::move(o.task)})):
task{std::move(o.task)}, n{std::move(o.n)} {}
using Signature = Signature_;
using Struct = S<alsk::Farm, typename Task::Struct>;
using Links = L<alsk::Farm, Signature, typename Task::Links>;
template<typename S>
constexpr void setup(S& skeleton) const {
skeleton.n = n;
setupFor(task, skeleton.task);
}
template<typename Signature>
constexpr auto link() const&& {
return Farm<Signature, Task>{std::move(*this)};
}
template<typename Signature>
constexpr auto link() const& {
return Farm<Signature, Task>{*this};
}
template<typename Rhs, std::enable_if_t<isOperand<Rhs>>* = nullptr>
constexpr auto select(Rhs const& rhs) {
return FarmSel<GetReturnType<Rhs>(), Task, Rhs>{task, rhs, n};
}
};
template<typename Signature = void(), typename Task, std::enable_if_t<isOperand<Task>>* = nullptr>
constexpr auto farm(Task const& task, unsigned int n = 0) {
return Farm<Signature, Task>{task, n};
}
template<typename Rhs, std::enable_if_t<isOperand<Rhs>>* = nullptr>
constexpr auto operator*(Rhs const& rhs) {
return Farm<void(), Rhs>{rhs, 0};
}
template<typename Rhs, std::enable_if_t<isOperand<Rhs>>* = nullptr>
constexpr auto operator*(unsigned int n, Rhs const& rhs) {
return Farm<void(), Rhs>{rhs, n};
}
template<typename Lhs, std::enable_if_t<isOperand<Lhs>>* = nullptr>
constexpr auto operator*(Lhs const& lhs, unsigned int n) {
return Farm<void(), Lhs>{lhs, n};
}
}
}
#endif

View File

@ -0,0 +1,70 @@
#ifndef ALSK_ALSK_EDSL_OP_IMPL_FARMSEL_H
#define ALSK_ALSK_EDSL_OP_IMPL_FARMSEL_H
#include <utility>
#include "../traits.h"
#include "../../../skeleton/bone/farmsel.h"
#include "../../../skeleton/struct/struct.h"
#include "../../../skeleton/link/link.h"
namespace alsk {
namespace edsl {
template<typename, typename> struct Farm;
template<typename Signature_, typename Task, typename Select>
struct FarmSel: OperandBase {
Task task;
Select select;
unsigned int n;
constexpr FarmSel(Task task, Select select, unsigned int n)
noexcept(noexcept(Task{std::move(task)}) and noexcept(Select{std::move(select)})):
task{std::move(task)}, select{std::move(select)}, n{n}
{}
template<typename S>
constexpr FarmSel(FarmSel<S, Task, Select> const& o)
noexcept(noexcept(Task{o.task}) and noexcept(Select{o.select})):
task{o.task}, select{o.select}, n{o.n}
{}
template<typename S>
constexpr FarmSel(FarmSel<S, Task, Select>&& o)
noexcept(noexcept(Task{std::move(o.task)}) and noexcept(Select{std::move(o.select)})):
task{std::move(o.task)}, select{std::move(o.select)}, n{std::move(o.n)}
{}
using Signature = Signature_;
using Struct = S<alsk::FarmSel, typename Task::Struct, typename Select::Struct>;
using Links = L<alsk::FarmSel, Signature, typename Task::Links, typename Select::Links>;
template<typename S>
constexpr void setup(S& skeleton) const {
skeleton.n = n;
setupFor(task, skeleton.task);
setupFor(select, skeleton.select);
}
template<typename Signature>
constexpr auto link() const&& {
return FarmSel<Signature, Task, Select>{std::move(*this)};
}
template<typename Signature>
constexpr auto link() const& {
return FarmSel<Signature, Task, Select>{*this};
}
};
template<typename FR, typename... FArgs, typename Task, typename Rhs, std::enable_if_t<isOperand<Rhs>>* = nullptr>
constexpr auto operator->*(Farm<FR(FArgs...), Task> const& farm, Rhs const& rhs) {
return FarmSel<GetReturnType<Rhs>(FArgs...), Task, Rhs>{farm.task, rhs, farm.n};
}
}
}
#endif

View File

@ -0,0 +1,99 @@
#ifndef ALSK_ALSK_EDSL_OP_IMPL_ITERSEL_H
#define ALSK_ALSK_EDSL_OP_IMPL_ITERSEL_H
#include <utility>
#include "../traits.h"
#include "../../../skeleton/bone/itersel.h"
#include "../../../skeleton/struct/struct.h"
#include "../../../skeleton/link/link.h"
namespace alsk {
namespace edsl {
template<typename, typename> struct Loop;
template<typename, typename, typename> struct FarmSel;
template<typename Signature_, typename Task, typename Select>
struct IterSel: OperandBase {
Task task;
Select select;
unsigned int n;
constexpr IterSel(Task task, Select select, unsigned int n)
noexcept(noexcept(Task{std::move(task)}) and noexcept(Select{std::move(select)})):
task{std::move(task)}, select{std::move(select)}, n{n}
{}
template<typename S>
constexpr IterSel(IterSel<S, Task, Select> const& o)
noexcept(noexcept(Task{o.task}) and noexcept(Select{o.select})):
task{o.task}, select{o.select}, n{o.n}
{}
template<typename S>
constexpr IterSel(IterSel<S, Task, Select>&& o)
noexcept(noexcept(Task{std::move(o.task)}) and noexcept(Select{std::move(o.select)})):
task{std::move(o.task)}, select{std::move(o.select)}, n{std::move(o.n)}
{}
using Signature = Signature_;
using Struct = S<alsk::IterSel, typename Task::Struct, typename Select::Struct>;
using Links = L<alsk::IterSel, Signature, typename Task::Links, typename Select::Links>;
template<typename S>
constexpr void setup(S& skeleton) const {
skeleton.n = n;
setupFor(task, skeleton.task);
setupFor(select, skeleton.select);
}
template<typename Signature>
constexpr auto link() const&& {
return IterSel<Signature, Task, Select>{std::move(*this)};
}
template<typename Signature>
constexpr auto link() const& {
return IterSel<Signature, Task, Select>{*this};
}
};
namespace impl {
template<typename, typename> struct Iter;
template<typename Task, typename R, typename... Args>
struct Iter<Task, R(Args...)> {
Task const& task;
unsigned int n;
template<typename Select, std::enable_if_t<isOperand<Select>>* = nullptr>
constexpr auto select(Select const& select) {
using Signature = GetReturnType<Select>(Args...);
return alsk::edsl::IterSel<Signature, Task, Select>{task, select, n};
}
};
}
template<typename Signature = void(), typename Task, std::enable_if_t<isOperand<Task>>* = nullptr>
constexpr auto iter(Task const& task, unsigned int n = 0) {
return impl::Iter<Task, Signature>{task, n};
}
template<typename Signature, typename Task, typename Select>
constexpr auto operator&(FarmSel<Signature, Task, Select> const& farmsel) {
return IterSel<Signature, Task, Select>{farmsel.task, farmsel.select, farmsel.n};
}
template<typename LR, typename... LArgs, typename Task, typename Rhs, std::enable_if_t<isOperand<Rhs>>* = nullptr>
constexpr auto operator->*(Loop<LR(LArgs...), Task> const& loop, Rhs const& rhs) {
return IterSel<GetReturnType<Rhs>(LArgs...), Task, Rhs>{loop.task, rhs, loop.n};
}
}
}
#endif

View File

@ -0,0 +1,73 @@
#ifndef ALSK_ALSK_EDSL_OP_IMPL_LOOP_H
#define ALSK_ALSK_EDSL_OP_IMPL_LOOP_H
#include <utility>
#include "../traits.h"
#include "../../../skeleton/bone/loop.h"
#include "../../../skeleton/struct/struct.h"
#include "../../../skeleton/link/link.h"
namespace alsk {
namespace edsl {
template<typename, typename> struct Farm;
template<typename Signature_, typename Task>
struct Loop: OperandBase {
Task task;
unsigned int n;
constexpr Loop(Task task, unsigned int n)
noexcept(noexcept(Task{std::move(task)})):
task{std::move(task)}, n{n}
{}
template<typename S>
constexpr Loop(Loop<S, Task> const& o)
noexcept(noexcept(Task{o.task})):
task{o.task}, n{o.n}
{}
template<typename S>
constexpr Loop(Loop<S, Task>&& o)
noexcept(noexcept(Task{std::move(o.task)})):
task{std::move(o.task)}, n{std::move(o.n)}
{}
using Signature = Signature_;
using Struct = S<alsk::Loop, typename Task::Struct>;
using Links = L<alsk::Loop, Signature, typename Task::Links>;
template<typename S>
constexpr void setup(S& skeleton) const {
skeleton.n = n;
setupFor(task, skeleton.task);
}
template<typename Signature>
constexpr auto link() const&& {
return Loop<Signature, Task>{std::move(*this)};
}
template<typename Signature>
constexpr auto link() const& {
return Loop<Signature, Task>{*this};
}
};
template<typename Signature = void(), typename Task>
constexpr auto loop(Task const& task, unsigned int n = 0) {
return Loop<Signature, Task>{task, n};
}
template<typename Signature, typename Task>
constexpr auto operator&(Farm<Signature, Task> const& farm) {
return Loop<Signature, Task>{farm.task, farm.n};
}
}
}
#endif

View File

@ -0,0 +1,67 @@
#ifndef ALSK_ALSK_EDSL_OP_IMPL_OPERAND_H
#define ALSK_ALSK_EDSL_OP_IMPL_OPERAND_H
#include <type_traits>
#include <utility>
#include "../../../skeleton/muscle/muscle.h"
namespace alsk {
namespace edsl {
struct OperandTag;
struct LeafTag;
struct OperandBase {
using IsOperand = OperandTag;
constexpr OperandBase() noexcept = default;
template<typename S, typename Operand, decltype(std::declval<Operand>().setup(std::declval<S&>()))* = nullptr>
constexpr void setupFor(Operand& operand, S& skeleton) const noexcept {
operand.setup(skeleton);
}
template<typename... Args>
constexpr void setupFor(Args&&...) const noexcept {}
};
template<typename Function_, typename Signature_>
struct Operand: OperandBase {
using IsLeaf = LeafTag;
using Function = Function_;
using Signature = Signature_;
using Struct = Function_;
using Links = Signature_;
constexpr Operand() noexcept = default;
template<typename Signature>
constexpr auto link() const noexcept { return Operand<Function, Signature>{}; }
};
template<typename Function>
constexpr auto makeOperand() noexcept {
return Operand<Function, void()>{};
}
template<typename Signature, typename Function>
constexpr auto makeOperand() noexcept {
return Operand<Function, Signature>{};
}
template<typename Signature, Signature function>
constexpr auto makeOperand() noexcept {
using Function = Fn<Signature, function>;
return Operand<Function, typename Function::Signature>{};
}
}
}
// TODO C++17
#define alskMakeOperand(f) makeOperand<decltype(f)&, f>()
#endif

View File

@ -0,0 +1,120 @@
#ifndef ALSK_ALSK_EDSL_OP_IMPL_SERIAL_H
#define ALSK_ALSK_EDSL_OP_IMPL_SERIAL_H
#include <utility>
#include "../traits.h"
#include "../../../skeleton/bone/serial.h"
#include "../../../skeleton/struct/struct.h"
#include "../../../skeleton/link/link.h"
namespace alsk {
namespace edsl {
template<typename Signature_, typename... Operands>
struct Serial: OperandBase {
std::tuple<Operands...> operands;
constexpr Serial(Operands... operands): operands{operands...} {}
template<typename S>
constexpr Serial(Serial<S, Operands...> const& o): operands{o.operands} {}
template<typename S>
constexpr Serial(Serial<S, Operands...>&& o): operands{std::move(o.operands)} {}
using Signature = Signature_;
using Struct = S<alsk::Serial, typename Operands::Struct...>;
using Links = L<alsk::Serial, Signature, typename Operands::Links...>;
template<typename S>
constexpr void setup(S& skeleton) const {
setup(skeleton, std::make_index_sequence<sizeof...(Operands)>());
}
template<typename S, std::size_t... indices>
constexpr void setup(S& skeleton, std::index_sequence<indices...>) const {
using Expander = int[];
static_cast<void>(Expander{(OperandBase::setupFor(std::get<indices>(operands), skeleton.template task<indices>()), 0)...});
}
template<typename Signature>
constexpr auto link() const&& {
return Serial<Signature, Operands...>{std::move(*this)};
}
template<typename Signature>
constexpr auto link() const& {
return Serial<Signature, Operands...>{*this};
}
};
namespace impl {
template<typename Lhs, std::size_t... lIndices, typename Rhs, std::size_t... rIndices>
constexpr auto mergeSerial(Lhs const& lhs, std::index_sequence<lIndices...>, Rhs const& rhs, std::index_sequence<rIndices...>) {
return Serial<void(), std::tuple_element_t<lIndices, Lhs>..., std::tuple_element_t<rIndices, Rhs>...>{
std::get<lIndices>(lhs)..., std::get<rIndices>(rhs)...
};
}
template<typename Lhs, typename Rhs>
constexpr auto mergeSerial(Lhs const& lhs, Rhs const& rhs) {
return mergeSerial(lhs, std::make_index_sequence<std::tuple_size<Lhs>{}>(),
rhs, std::make_index_sequence<std::tuple_size<Rhs>{}>());
}
template<typename T>
constexpr auto operandTuple(T const& t) {
return std::make_tuple(t);
}
template<typename... Ts>
constexpr auto operandTuple(Serial<Ts...> const& s) noexcept {
return s.operands;
}
template<typename...> struct SerialBuilder;
template<typename Arg, typename... Args>
struct SerialBuilder<Arg, Args...> {
static constexpr auto build(Arg const& arg, Args const&... args) {
return mergeSerial(operandTuple(arg), operandTuple(SerialBuilder<Args...>::build(args...)));
}
};
template<typename Arg>
struct SerialBuilder<Arg> {
static constexpr auto build(Arg const& arg) {
return arg;
}
};
}
template<typename... Args, std::enable_if_t<(sizeof...(Args) > 1) and allOperands<Args...>>* = nullptr>
constexpr auto serial(Args const&... args) {
return impl::SerialBuilder<Args...>::build(args...);
}
template<
typename Lhs, typename Rhs,
std::enable_if_t<isOperand<Lhs> and isOperand<Rhs>>* = nullptr
>
constexpr auto operator,(Lhs const& lhs, Rhs const& rhs) {
return impl::mergeSerial(impl::operandTuple(lhs), impl::operandTuple(rhs));
}
template<
typename Lhs, typename Rhs,
std::enable_if_t<isOperand<Lhs> and isOperand<Rhs>>* = nullptr
>
constexpr auto operator&(Lhs const& lhs, Rhs const& rhs) {
return impl::mergeSerial(impl::operandTuple(lhs), impl::operandTuple(rhs));
}
}
}
#endif

View File

@ -0,0 +1,80 @@
#ifndef ALSK_ALSK_EDSL_OP_IMPL_WHILE_H
#define ALSK_ALSK_EDSL_OP_IMPL_WHILE_H
#include <utility>
#include "../traits.h"
#include "../../../skeleton/bone/while.h"
#include "../../../skeleton/struct/struct.h"
#include "../../../skeleton/link/link.h"
namespace alsk {
namespace edsl {
template<typename Signature_, typename Cond, typename Task>
struct While: OperandBase {
Cond cond;
Task task;
constexpr While(Cond cond, Task task)
noexcept(noexcept(Cond{std::move(cond)}) and noexcept(Task{std::move(task)})):
cond{std::move(cond)}, task{std::move(task)}
{}
template<typename S>
constexpr While(While<S, Cond, Task> const& o)
noexcept(noexcept(Cond{o.cond}) and noexcept(Task{o.task})):
cond{o.cond}, task{o.task}
{}
template<typename S>
constexpr While(While<S, Cond, Task>&& o)
noexcept(noexcept(Cond{std::move(o.cond)}) and noexcept(Task{std::move(o.task)})):
cond{std::move(o.cond)}, task{std::move(o.task)}
{}
using Signature = Signature_;
using Struct = S<alsk::While, typename Cond::Struct, typename Task::Struct>;
using Links = L<alsk::While, Signature, typename Cond::Links, typename Task::Links>;
template<typename S>
constexpr void setup(S& skeleton) const {
setupFor(cond, skeleton.cond);
setupFor(task, skeleton.task);
}
template<typename Signature>
constexpr auto link() const&& {
return While<Signature, Cond, Task>{std::move(*this)};
}
template<typename Signature>
constexpr auto link() const& {
return While<Signature, Cond, Task>{*this};
}
};
namespace impl {
template<typename Cond, typename Signature>
struct WhilePart {
Cond const& cond;
template<typename Task, std::enable_if_t<isOperand<Task>>* = nullptr>
constexpr auto do_(Task const& task) {
return alsk::edsl::While<Signature, Cond, Task>{cond, task};
}
};
}
template<typename Signature = void(), typename Cond, std::enable_if_t<isOperand<Cond>>* = nullptr>
constexpr auto while_(Cond const& cond) {
return impl::WhilePart<Cond, Signature>{cond};
}
}
}
#endif

12
inc/alsk/edsl/op/op.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef ALSK_ALSK_EDSL_OP_OP_H
#define ALSK_ALSK_EDSL_OP_OP_H
#include "impl/farm.h"
#include "impl/farmsel.h"
#include "impl/itersel.h"
#include "impl/loop.h"
#include "impl/operand.h"
#include "impl/serial.h"
#include "impl/while.h"
#endif

82
inc/alsk/edsl/op/traits.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef ALSK_ALSK_EDSL_OP_TRAITS_H
#define ALSK_ALSK_EDSL_OP_TRAITS_H
#include <type_traits>
#include "impl/operand.h"
namespace alsk {
namespace edsl {
/**
* @brief true if the type is an operand for the EDSL
*/
template<typename, typename=void> struct IsOperand: std::false_type {};
template<typename T>
struct IsOperand<T, std::enable_if_t<std::is_same<typename T::IsOperand, OperandTag>{}>>: std::true_type {};
template<typename T>
constexpr bool isOperand = IsOperand<T>::value;
/**
* @brief true if all the types are operands for the EDSL
*/
template<typename...> struct AllOperands;
template<typename T, typename... Ts>
struct AllOperands<T, Ts...> {
static constexpr bool value = isOperand<T> && AllOperands<Ts...>::value;
};
template<>
struct AllOperands<>: std::true_type {};
template<typename... Ts>
constexpr bool allOperands = AllOperands<Ts...>::value;
/**
* @brief true if the type is a leaf
*/
template<typename, typename=void> struct IsLeaf: std::false_type {};
template<typename T>
struct IsLeaf<T, std::enable_if_t<std::is_same<typename T::IsLeaf, LeafTag>{}>>: std::true_type {};
template<typename T>
constexpr bool isLeaf = IsLeaf<T>::value;
/**
* @brief true if the type is a branch
*/
template<typename, typename=void> struct IsBranch: std::false_type {};
template<typename T>
struct IsBranch<T, std::enable_if_t<isOperand<T> and not isLeaf<T>>>: std::true_type {};
template<typename T>
constexpr bool isBranch = IsBranch<T>::value;
/**
* @brief get the return value from an operand's signature
*/
template<typename> struct GetReturnTypeFromSignatureImpl;
template<typename R, typename... Args>
struct GetReturnTypeFromSignatureImpl<R(Args...)> {
using type = R;
};
template<typename Signature>
using GetReturnTypeFromSignature = typename GetReturnTypeFromSignatureImpl<Signature>::type;
/**
* @brief get the return value from an operand
*/
template<typename T>
using GetReturnType = GetReturnTypeFromSignature<typename T::Signature>;
}
}
#endif