1c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// -*- C++ -*-
2c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert//===----------------------------------------------------------------------===//
3c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert//
4c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert//                     The LLVM Compiler Infrastructure
5c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert//
6c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// This file is dual licensed under the MIT and the University of Illinois Open
7c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert// Source Licenses. See LICENSE.TXT for details.
8c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert//
9c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert//===----------------------------------------------------------------------===//
10c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
11c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#ifndef SUPPORT_COROUTINE_TYPES_H
12c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#define SUPPORT_COROUTINE_TYPES_H
13c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
14c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#include <experimental/coroutine>
15c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
16c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Alberttemplate <typename Ty> struct generator {
17c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  struct promise_type {
18c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    Ty current_value;
19c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    std::experimental::suspend_always yield_value(Ty value) {
20c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      this->current_value = value;
21c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      return {};
22c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    }
23c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    std::experimental::suspend_always initial_suspend() { return {}; }
24c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    std::experimental::suspend_always final_suspend() { return {}; }
25c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    generator get_return_object() { return generator{this}; };
26c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    void return_void() {}
27c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    void unhandled_exception() {}
28c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  };
29c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
30c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  struct iterator {
31c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    std::experimental::coroutine_handle<promise_type> _Coro;
32c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    bool _Done;
33c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
34c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    iterator(std::experimental::coroutine_handle<promise_type> Coro, bool Done)
35c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert        : _Coro(Coro), _Done(Done) {}
36c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
37c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    iterator &operator++() {
38c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      _Coro.resume();
39c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      _Done = _Coro.done();
40c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      return *this;
41c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    }
42c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
43c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    bool operator==(iterator const &_Right) const {
44c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      return _Done == _Right._Done;
45c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    }
46c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
47c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    bool operator!=(iterator const &_Right) const { return !(*this == _Right); }
48c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
49c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    Ty const &operator*() const { return _Coro.promise().current_value; }
50c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
51c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    Ty const *operator->() const { return &(operator*()); }
52c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  };
53c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
54c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  iterator begin() {
55c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    p.resume();
56c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    return {p, p.done()};
57c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
58c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
59c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  iterator end() { return {p, true}; }
60c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
61c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  generator(generator &&rhs) : p(rhs.p) { rhs.p = nullptr; }
62c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
63c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  ~generator() {
64c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert    if (p)
65c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      p.destroy();
66c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  }
67c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
68c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albertprivate:
69c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  explicit generator(promise_type *p)
70c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert      : p(std::experimental::coroutine_handle<promise_type>::from_promise(*p)) {}
71c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
72c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert  std::experimental::coroutine_handle<promise_type> p;
73c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert};
74c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert
75c79549b70e66c251c15dd145c964edb70fa2e2b3Dan Albert#endif // SUPPORT_COROUTINE_TYPES_H
76