mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
e1b283b0b6
RecursiveCoroutines are a facility intended to be used as-drop in
replacement of recursive functions.
They provide the following features.
- They can be written almost as regular recursive functions,
with 4 caveats.
1. A recursive coroutine that returns a type `T`, needs to be declared
to return a `RecursiveCoroutine<T>`.
2. Inside the body of a recursive coroutine, when recursively calling
another recursive coroutine, the recursive call needs to be
prepended by the new keyword `rc_recur`.
3. Inside the body of a recursive coroutine, the `return` statement
needs to be substituted with `rc_return`.
4. When launching a recursive coroutine `A` from a function that is
not a recursive coroutine, `A` needs to be called with the provided
dedicated template wrapper `rc_run`.
The syntax is the following `rc_run(A, arg0, arg1, ...)`.
This is necessary to enable swapping off recursive coroutine and
fall back to regular recursion for debug.
See below for how to do it.
- Unlike regular recursive functions, they don't use the system stack
for recursion. They use a custom heap-allocated stack to manage
recursion. This makes them more robust for implementing recursive
functions that manipulate user-defined input, because they are much
less likely to trigger stack overflow.
- They can be turned off compiling with
`-DDISABLE_RECURSIVE_COROUTINES`, falling back to regular recursion,
for debug purposes.
- They support both direct and indirect recursion, i.e. a recursive
coroutine A can recursively call itself, or it can recursively call
another recursive coroutine B, which in turns recursively calls A.
39 lines
710 B
C++
39 lines
710 B
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
#include "revng/ADT/RecursiveCoroutine.h"
|
|
|
|
struct MyState {
|
|
int Depth;
|
|
};
|
|
|
|
inline RecursiveCoroutine<int> get10() {
|
|
rc_return 10;
|
|
}
|
|
|
|
inline RecursiveCoroutine<> my_coroutine(std::vector<MyState> &RCS, int x) {
|
|
int X = 1;
|
|
std::cerr << "Pre " << x << ':';
|
|
RCS.back().Depth = x;
|
|
|
|
for (const MyState &S : RCS) {
|
|
std::cerr << ' ' << S.Depth;
|
|
}
|
|
std::cerr << std::endl;
|
|
|
|
if (x < (rc_recur get10())) {
|
|
RCS.emplace_back();
|
|
rc_recur my_coroutine(RCS, x + 1);
|
|
}
|
|
|
|
std::cerr << "Post " << x << ' ' << X << std::endl;
|
|
RCS.pop_back();
|
|
rc_return;
|
|
}
|