Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix loop #32

Merged
merged 2 commits into from
Jul 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 29 additions & 11 deletions include/hspp.h
Original file line number Diff line number Diff line change
Expand Up @@ -3519,9 +3519,27 @@ namespace doN
template <typename T>
class Nullary;

class LetExpr
{};
constexpr LetExpr letExpr{};
template <typename F>
class LetExpr : public F
{
public:
LetExpr(F f)
: F{std::move(f)}
{}
};

template <typename T>
class IsLetExpr : public std::false_type
{
};

template <typename T>
class IsLetExpr<LetExpr<T>> : public std::true_type
{
};

template <typename T>
constexpr auto isLetExprV = IsLetExpr<std::decay_t<T>>::value;

// make sure Id is not a const obj.
template <typename T>
Expand Down Expand Up @@ -3551,16 +3569,15 @@ class Id
constexpr auto operator=(T const& d)
{
bind(d);
return letExpr;
return LetExpr([]{});
}

// return let expr
template <typename F>
constexpr auto operator=(Nullary<F> const& f)
{
static_assert(std::is_same_v<T, std::invoke_result_t<Nullary<F>>>);
bind(f());
return letExpr;
return LetExpr([*this, f]{ bind(f()); });
}

};
Expand Down Expand Up @@ -3600,9 +3617,9 @@ class IsNullary<Nullary<T>> : public std::true_type
};

template <typename T>
constexpr auto isNullary = IsNullary<std::decay_t<T>>::value;
constexpr auto isNullaryV = IsNullary<std::decay_t<T>>::value;

template <typename ClassT, typename T , typename = std::enable_if_t<isNullary<T>, void>>
template <typename ClassT, typename T , typename = std::enable_if_t<isNullaryV<T>, void>>
constexpr auto evalDeferredImpl(T&& t)
{
static_assert(std::is_same_v<MonadType<ClassT>, MonadType<std::invoke_result_t<T>>>);
Expand Down Expand Up @@ -3759,9 +3776,10 @@ constexpr auto doImplNullaryDeMonad(Nullary<N> const& dmN, Rest const&... rest)
return doImpl<MClass>(dmN(), rest...);
}

template <typename MClass1, typename... Rest>
constexpr auto doImpl(LetExpr, Rest const&... rest)
template <typename MClass1, typename F, typename... Rest>
constexpr auto doImpl(LetExpr<F> const& le, Rest const&... rest)
{
le();
return evaluate_(doImpl<MClass1>(rest...));
}

Expand All @@ -3773,7 +3791,7 @@ constexpr auto doImpl(DeMonad<MClass2> const& dm, Rest const&... rest)
return dm.m() >>= funcWithParams(dm.id(), bodyBaker);
}

template <typename MClass, typename Head, typename... Rest, typename = std::enable_if_t<!isDeMonadV<Head> && !std::is_same_v<Head, LetExpr>, void>>
template <typename MClass, typename Head, typename... Rest, typename = std::enable_if_t<!isDeMonadV<Head> && !isLetExprV<Head>, void>>
constexpr auto doImpl(Head const& head, Rest const&... rest)
{
if constexpr (isNullaryOrIdV<Head>)
Expand Down
78 changes: 62 additions & 16 deletions test/hspp/stm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,50 +217,96 @@ TEST(MVar, 3)
// io_.run();
}

#if 0
class Message : public std::string{};
class Stop : public MVar<_O_>{};

using LogCommand = std::variant<Message, Stop>;
class Logger : public MVar<LogCommand>{};

constexpr auto toStop = toFunc<> | [](MVar<_O_> mo)
{
return Stop{std::move(mo)};
};

auto logger(Logger& m)
constexpr auto toLogCommnad = toGFunc<1> | [](auto l)
{
IO<_O_> loop0 = []{ return _o_; };
auto loop = loop0;
return LogCommand{std::move(l)};
};

constexpr auto toLogger = toFunc<> | [](MVar<LogCommand> mlc)
{
return Logger{std::move(mlc)};
};

auto const dispatchCmd = toFunc<> | [&loop](LogCommand const& lc)
const auto logger = toFunc<> | [] (Logger m)
{
auto const dispatchCmd = toGFunc<2> | [](LogCommand const& lc, auto const& loop)
{
return std::visit(overload(
[&](Message const& msg){
return toTEIO | do_(print | msg, loop);
return toTEIO | do_(print | msg, loop());
},
[](Stop s){
return toTEIO | do_(putStrLn | "logger: stop", putMVar | s | _o_);
}
), lc);
};

Id<LogCommand> cmd;
loop = toTEIO | do_(
cmd <= (takeMVar | m),
dispatchCmd | cmd
);
}

constexpr auto initLoggerImpl()
auto loop = yCombinator | [=](auto const& self) -> IO<_O_>
{
Id<LogCommand> cmd;
return toTEIO | do_(
cmd <= (takeMVar | m),
dispatchCmd | cmd | self
);
};
return loop();
};

auto initLogger()
{
Id<LogCommand> m;
Id<MVar<LogCommand>> m;
Id<Logger> l;
return do_(
m <= newEmptyMVar<LogCommand>,
l = (Logger | m),
l = (toLogger | m),
forkIO | (logger | l),
return_ | l
);
}
#endif // 0

constexpr auto logMessage = toFunc<> | [](Logger m, std::string s)
{
return putMVar | m | LogCommand{Message{s}};
};

constexpr auto logStop = toFunc<> | [](Logger m)
{
Id<MVar<_O_>> s;
return do_(
s <= newEmptyMVar<_O_>,
putMVar | m || (toLogCommnad || toStop | s),
takeMVar | s
);
};

TEST(MVar, logger)
{
Id<Logger> l;
auto io_ = do_(
l <= initLogger(),
logMessage | l | "hello",
logMessage | l | "bye",
logStop | l
);

testing::internal::CaptureStdout();
io_.run();
std::string output = testing::internal::GetCapturedStdout();
EXPECT_EQ(output, "hello\nbye\nlogger: stop\n");
}


template <typename A>
struct IORef
Expand Down