> turns it into some sort of ugly state machine

Why are people afraid of state machines? There's been sooo much effort spent on hiding them from the programmer...

They're essentially callable, stateful, structured gotos. Difficult to understand for the uninitiated.

For example, generators. Also known as semicoroutines.

https://langdev.stackexchange.com/a/834

This:

  generator fib() {
      a, b = 1, 2
      while (a<100) {
          b, a = a, a+b
          yield a
      }
      yield a-1
  }
Becomes this:

  struct fibState {
      a,
      b,
      position
  }

  int fib(fibState state) {
      switch (fibState.postion) {
          case 0:
              fibState.a, fibState.b = 1,2
              while (a<100) {
                  fibState.b, fibState.a = fibState.a, fibState.a+fibState.b
                  // switching the context
                  fibState.position = 1;
                  return fibState.a;
          case 1:
              }

              fibState.position = 2;
              return fibState.a-1
          case 2:
              fibState.position = -1;
      }
  }
The ugly state machine example presented in the article is also a manual implementation of a generator. It's as palatable to the normal programmer as raw compiler output. Being written in C++ makes it even uglier and more complicated.

The programming language I made is a concrete example of what programming these things manually is like. I had to write every primitive as a state machine just like the one above.

https://www.matheusmoreira.com/articles/delimited-continuati...

What you've given is an example of how to implement a coroutine though.

Not of how to write a state machine based application without hiding the state machine behind abstractions.

Because they are unstructured and non-modular. And yes, graphical notation sucks.