128 lines
3.5 KiB
C++
128 lines
3.5 KiB
C++
#include <catch.hpp>
|
|
#include <alsk/alsk.h>
|
|
|
|
using namespace alsk::arg;
|
|
using namespace alsk::edsl;
|
|
|
|
static int counterDo, counterThen, counterDone;
|
|
|
|
struct Do { void operator()() { ++counterDo; } };
|
|
struct Then { void operator()() { ++counterThen; } };
|
|
struct Done { void operator()() { ++counterDone; } };
|
|
|
|
struct Produce0 { int operator()(int x) { return x+1; } };
|
|
struct Produce1 { int operator()(int x) { return x-2; } };
|
|
struct Consume { int operator()(int x, int y) { return x*y; } };
|
|
|
|
// TODO? avoid copies so it is truly stateful
|
|
struct Generate { int value; int operator()(int b) { return ++value+b; } };
|
|
struct Transform0 { int operator()(int x) { return x+1; } };
|
|
struct Transform1 { int operator()(int x) { return x-2; } };
|
|
struct Produce { int operator()(int x, int y) { return x*y; } };
|
|
struct Select {
|
|
int mod;
|
|
int operator()(int a, int b) { if(a%mod == b%mod) return std::min(a, b); return (a%mod > b%mod)? a : b; }
|
|
};
|
|
|
|
TEST_CASE("edsl") {
|
|
auto aDo = makeOperand<Do>();
|
|
auto aThen = makeOperand<Then>();
|
|
auto aDone = makeOperand<Done>();
|
|
|
|
auto aProduce0 = makeOperand<Produce0>();
|
|
auto aProduce1 = makeOperand<Produce1>();
|
|
auto aConsume = makeOperand<Consume>();
|
|
|
|
auto e0 = aDo & (5*aThen) & aDone;
|
|
using E0 = decltype(e0);
|
|
using S0 = alsk::S<alsk::Serial, Do, alsk::S<alsk::Farm, Then>, Done>;
|
|
using L0 = alsk::L<alsk::Serial, void(), void(), alsk::L<alsk::Farm, void(), void()>, void()>;
|
|
|
|
auto e1 = 5*(aDo, 2*aThen, aDone);
|
|
using E1 = decltype(e1);
|
|
using S1 = alsk::S<alsk::Farm, alsk::S<alsk::Serial, Do, alsk::S<alsk::Farm, Then>, Done>>;
|
|
using L1 = alsk::L<alsk::Farm, void(), alsk::L<alsk::Serial, void(), void(), alsk::L<alsk::Farm, void(), void()>, void()>>;
|
|
|
|
auto e2 = link<R<2>(int)>(
|
|
link<int(P<0>)>(aProduce0),
|
|
link<int(P<0>)>(aProduce1),
|
|
link<int(R<1>, R<0>)>(aConsume)
|
|
);
|
|
|
|
SECTION("Construction") {
|
|
REQUIRE(std::is_same<E0::Signature, void()>{});
|
|
REQUIRE(std::is_same<E0::Struct, S0>{});
|
|
REQUIRE(std::is_same<E0::Links, L0>{});
|
|
|
|
REQUIRE(std::is_same<E1::Signature, void()>{});
|
|
REQUIRE(std::is_same<E1::Struct, S1>{});
|
|
REQUIRE(std::is_same<E1::Links, L1>{});
|
|
}
|
|
|
|
SECTION("Linking") {
|
|
{
|
|
auto f2 = implement<alsk::exec::Sequential>(e2);
|
|
|
|
REQUIRE(f2(0) == -2);
|
|
REQUIRE(f2(2) == 0);
|
|
REQUIRE(f2(5) == 18);
|
|
}
|
|
|
|
}
|
|
|
|
SECTION("Setup") {
|
|
auto f0 = implement<alsk::exec::Sequential>(e0);
|
|
|
|
REQUIRE(f0.skeleton.task<1>().n == 5);
|
|
}
|
|
|
|
SECTION("Check run") {
|
|
{
|
|
auto f0 = implement<alsk::exec::Sequential>(e0);
|
|
|
|
counterDo = counterThen = counterDone = 0;
|
|
f0();
|
|
|
|
REQUIRE(counterDo == 1);
|
|
REQUIRE(counterThen == 5);
|
|
REQUIRE(counterDone == 1);
|
|
}
|
|
|
|
{
|
|
auto f1 = implement<alsk::exec::Sequential>(e1);
|
|
|
|
counterDo = counterThen = counterDone = 0;
|
|
f1();
|
|
|
|
REQUIRE(counterDo == 5);
|
|
REQUIRE(counterThen == 10);
|
|
REQUIRE(counterDone == 5);
|
|
}
|
|
}
|
|
|
|
SECTION("Complex case") {
|
|
auto generate = makeOperand<Generate>();
|
|
auto transform0 = makeOperand<Transform0>();
|
|
auto transform1 = makeOperand<Transform1>();
|
|
auto produce = makeOperand<Produce>();
|
|
auto select = makeOperand<int(int, int), Select>();
|
|
|
|
auto innerTask = link<R<3>(int)>(
|
|
link<int(P<0>)>(generate),
|
|
link<int(R<0>)>(transform0),
|
|
link<int(R<0>)>(transform1),
|
|
link<int(R<2>, R<1>)>(produce)
|
|
);
|
|
auto task = link<int(int)>(10 * link<R<3>(P<0>)>(innerTask)) ->* select;
|
|
|
|
auto f = implement<alsk::exec::Sequential>(task);
|
|
f.skeleton.select.mod = 5;
|
|
|
|
REQUIRE(f(4) == 18);
|
|
REQUIRE(f(5) == 28);
|
|
REQUIRE(f(6) == 40);
|
|
REQUIRE(f(7) == 54);
|
|
REQUIRE(f(8) == 70);
|
|
}
|
|
}
|