Thus far, the only control flow mechanism you've been shown was the `label` construct for creating labeled scopes. But this one construct was powerful enough to express early returns from functions, early breaks from loops, and also (though we haven't shown it) early jumps to the next loop iteration. Each of the above functionality has traditionally been a separate keyword and language feature in other languages, but they're all expressible with just the `label` construct in Stanza. It is a powerful and general mechanism.

In actuality, Stanza only has a single control flow mechanism, called targetable coroutines. The `label` construct is just a common usage pattern for them. In this chapter we'll learn about the other common usage pattern of coroutines: attempts and failures, exception handlers, and generators. At the very end, we'll show you the general coroutine construct, along with some examples demonstrating their use.

## First Class Labeled Scopes

Here is a function that finds the smallest power of two that is greater or equal to the given argument, `n`.

``defn min-pow-2 (n:Int) :   label<Int> return :      var x = 1      while true :         if x >= n : return(x)         x = x * 2      fatal("Unreachable")   ``

Let's try it out.

``defn main () :   defn test (n:Int) :      println("The minimum power of 2 greater or equal to %_ is %_." %              [n, min-pow-2(n)])   test(10)   test(100)   test(1000)   test(10000)   test(100000)   test(1000000)main()``

Compiling and running the above prints out

``The minimum power of 2 greater or equal to 10 is 16.The minimum power of 2 greater or equal to 100 is 128.The minimum power of 2 greater or equal to 1000 is 1024.The minimum power of 2 greater or equal to 10000 is 16384.The minimum power of 2 greater or equal to 100000 is 131072.The minimum power of 2 greater or equal to 1000000 is 1048576.``

### Pulling Out the Body

That's fairly standard so far. But now let's pull out the body of the while loop into a separate function, called `pow-2?`. It accepts an argument, `x`, that is the current number being tested, an argument, `n`, as the limit we're trying to reach, and also a function called `return`, which we'll explain later.

``defn pow-2? (x:Int, n:Int, return:Int -> Void) -> Int :   if x >= n : return(x)   else : x * 2``

`pow-2?` first checks whether `x` is greater or equal to `n`, and calls `return` with `x` if it is. Otherwise it returns the next value of `x` to `test`, which is `x * 2`.

We now update the `min-pow-2` function to call `pow-2?`.

``defn min-pow-2 (n:Int) :   label<Int> return :      var x = 1      while true :         x = pow-2?(x, n, return)      fatal("Unreachable")``

Compile and run the program to verify that it still works.

What is happening here!? We've somehow passed the exit function out of `min-pow-2` and into `pow-2?`. Then when `pow-2?` called `return`, it returned not from `pow-2?`, but from `min-pow-2`!.

Let's review the definition of the `label` construct. Here is its general form.

``label<T> exit :   body``

The `label` construct requires the type it returns, `T`, the name of the exit function, `exit`, and the body to execute, `body``label` creates an exit function of type `T -> Void` with the name `exit`, and then executes `body`. If `body` never calls the exit function then the result of `body` is returned by `label`. If `body` calls the exit function then `label` immediately returns the argument passed to the exit function. The return type `Void` for the exit function indicates that it doesn't return to its caller.

There is nothing in the description of `label` preventing us from passing out the exit function, so the call to `return` in `pow-2?` is simply causing the `label` construct to return `x`, which is then returned by `min-pow-2`.

### Storing the Exit Function

We can even store the exit function in a variable if we like. Here's a global variable

``var RETURN: Int -> Void``

into which we will store the exit function. Thus the exit function will no longer be passed in to `pow-2?` as an argument.

``defn pow-2? (x:Int, n:Int) -> Int :   if x >= n : RETURN(x)   else : x * 2``

It will instead be stored in the global variable before `pow-2?` is called.

``defn min-pow-2 (n:Int) :   label<Int> return :      RETURN = return      var x = 1      while true :                  x = pow-2?(x, n)      fatal("Unreachable")``

Compile and verify that the program still works as before.

Here you're starting to see just how flexible the `label` construct really is. Storing the exit function seems like a strange thing to want to do but keep it in the back of your mind as we talk about the other constructs.

## Dynamic Wind

One of the issues that accompanies having a powerful control flow mechanism is that in a sequence of expressions, evaluating the first expression does not guarantee that the last one will be evaluated.

``f()g()h()``

For example, in the above sequence, even after `f` returns, there is no guarantee that `h` will be called. If `g` calls an exit function then `h` will be skipped entirely.

Let us suppose that we do not want to pass in the limit, `n`, as an argument to `pow-2?`. We would like to keep it stored in a global variable called `LIMIT` and set it to the appropriate value only during the call to `pow-2?`. At all other times, `LIMIT` should retain its initial value of `0`. Here is an initial attempt.

``var LIMIT: Int = 0var RETURN: Int -> Voiddefn pow-2? (x:Int) -> Int :   if x >= LIMIT : RETURN(x)   else : x * 2defn min-pow-2 (n:Int) :   label<Int> return :      RETURN = return            var x = 1      while true :         val old-limit = LIMIT         LIMIT = n         x = pow-2?(x)         LIMIT = old-limit      fatal("Unreachable")defn main () :   defn test (n:Int) :      println("The minimum power of 2 greater or equal to %_ is %_." %              [n, min-pow-2(n)])   test(10)   test(100)   test(1000)   test(10000)   test(100000)   test(1000000)main()println("After main, LIMIT is %_." % [LIMIT])``

Printing and compiling the above prints out

``The minimum power of 2 greater or equal to 10 is 16.The minimum power of 2 greater or equal to 100 is 128.The minimum power of 2 greater or equal to 1000 is 1024.The minimum power of 2 greater or equal to 10000 is 16384.The minimum power of 2 greater or equal to 100000 is 131072.The minimum power of 2 greater or equal to 1000000 is 1048576.After main, LIMIT is 1000000.``

So `min-pow-2` is working correctly, but `LIMIT` is not being restored back to its original value. What is happening? Well the call to `pow-2?` in

``LIMIT = nx = pow-2?(x)LIMIT = old-limit``

may call the exit function, `return`. If that happens, then the `label` construct immediately returns and the last `LIMIT = old-limit` expression is never evaluated.

Stanza provides the special function `dynamic-wind` to handle these situations. It allows you to surround a body of code between some wind in and wind out code. The wind in code is guaranteed to execute whenever the control flow enters the body, and the wind out code is guaranteed to execute whenever the control flow exits the body. Here is how it's used.

``defn min-pow-2 (n:Int) :   label<Int> return :      RETURN = return            var x = 1      while true :         val old-limit = LIMIT         dynamic-wind(            fn () :               LIMIT = n            fn () :                  x = pow-2?(x)            fn (final) :                           LIMIT = old-limit)      fatal("Unreachable")``

The wind in, body, and wind out code is given to `dynamic-wind` as three anonymous functions. The `final` argument for the wind out code is a boolean value that indicates whether it is guaranteed to be the last time the wind out code is called. In this example, `final` will always be `true`

Now compiling and running the program again prints out

``The minimum power of 2 greater or equal to 10 is 16.The minimum power of 2 greater or equal to 100 is 128.The minimum power of 2 greater or equal to 1000 is 1024.The minimum power of 2 greater or equal to 10000 is 16384.The minimum power of 2 greater or equal to 100000 is 131072.The minimum power of 2 greater or equal to 1000000 is 1048576.After main, LIMIT is 0.``

indicating the `LIMIT` is properly being reset to its original value.

## Dynamically Scoped Variables

In the above example, we say that `LIMIT` is being used as a dynamically scoped variable. This is a common pattern and Stanza provides a syntactic shorthand for our call to `dynamic-wind`.

Here is the `min-pow-2` function written using the `let-var` shorthand.

``defn min-pow-2 (n:Int) :   label<Int> return :      RETURN = return            var x = 1      while true :         let-var LIMIT = n :            x = pow-2?(x)      fatal("Unreachable")``

The general form of `let-var` is

``let-var x = v :   body``

It temporarily sets the `x` variable to the value `v` before executing `body``x` is restored to its previous value after `body` is finished executing.

## Attempts and Failures

Attempts and failures are syntactic sugar for another use case of targetable coroutines that operate very similarly to labeled scopes. Here is an example.

``defn read-letter (xs:Seq<Char>) -> Char :   if not letter?(peek(xs)) : fail()   next(xs)defn read-digit (xs:Seq<Char>) -> Char :   if not digit?(peek(xs)) : fail()   next(xs)defn read-all (xs:Collection<Char>) :   val xs-seq = to-seq(xs)   while not empty?(xs-seq) :      attempt :          println("Read letter: %_" % [read-letter(xs-seq)])      else attempt :         println("Read digit: %_" % [read-digit(xs-seq)])      else :         println("Read something else: %~" % [next(xs-seq)])read-all("42 is the answer.")         ``

Compiling the above prints out

``Read digit: 4Read digit: 2Read something else: ' 'Read letter: iRead letter: sRead something else: ' 'Read letter: tRead letter: hRead letter: eRead something else: ' 'Read letter: aRead letter: nRead letter: sRead letter: wRead letter: eRead letter: rRead something else: '.'``

The function `read-all` calls `read-letter` and `read-digit` in an `attempt` block. If the block evaluates without ever calling `fail` then the result of the block is returned by `attempt`. If the block calls `fail`, then `attempt` immediately returns the result of evaluating the code in the `else` branch.

## Example: S-Expression Parser

Here is an example of using `attempt` and `fail` to program a simple s-expression parser. An s-expression, in this case, will be defined as either

1. a positive integer,
2. a symbol consisting of letters,
3. or a list containing more s-expressions.

### Overall Structure

Here is the basic structure of the parser.

``defn parse-sexp (sexp:String) -> List :   val chars = to-seq(sexp)   defn eat-while (pred?: Char -> True|False) -> String :      ...   defn eat-whitespace () -> False :      ... calls eat-while ...      defn parse-symbol () -> Symbol :      ... calls eat-while ...            defn parse-number () -> Int :      ... calls eat-while ...   defn parse-sequence () -> List :      ... calls eat-whitespace, parse-symbol, parse-number, and parse-list         defn parse-list () -> List :      ... calls parse-list ...   parse-sequence()   ...``

parse-sexp is given a string, and returns a list of s-expressions. Upon entering the function, we ask to view the string as a sequence of characters, `chars``eat-while` and `eat-whitespace` are helper functions. `parse-symbol``parse-number``parse-sequence`, and `parse-list` are mutually recursive functions that parse symbols, numbers, sequences of s-expressions, and lists of s-expressions.

### Helper Functions

The `eat-while`, and `eat-whitespace` functions are helper functions for reading from `chars``eat-while` takes a predicate function, `pred?`, and eats characters from `chars` as long as `pred?` returns `true`. It returns a string containing the eaten characters. `eat-whitespace` eats all leading spaces in `chars`. Here are their definitions.

``defn eat-while (pred?: Char -> True|False) -> String :   string-join(take-while(pred?, chars))defn eat-whitespace () -> False :   eat-while({_ == ' '})   false``

### Parsing Symbols

The `parse-symbol` function eats and returns the next symbol from `chars`. If the next character in `chars` is not a letter, then `parse-symbol` fails.

``defn parse-symbol () -> Symbol :   if not letter?(peek(chars)) : fail()   to-symbol(eat-while(letter?))``

### Parsing Numbers

The `parse-number` function eats and returns the next positive integer from `chars`. If the next character in `chars` is not a digit, or if the number cannot be represented in 32 bits, then `parse-number` fails.

``defn parse-number () -> Int :   if not digit?(peek(chars)) : fail()   val x = to-int(eat-while(digit?))   if x is-not Int : fail()   x as Int``

### Parsing Sequences

The `parse-sequence` function reads as many s-expressions as possible by calling `parse-symbol``parse-number`, and `parse-list` repeatedly.

``defn parse-sequence () -> List :   eat-whitespace()   if empty?(chars) :      List()   else :      attempt : cons(parse-symbol(), parse-sequence())      else attempt : cons(parse-number(), parse-sequence())      else attempt : cons(parse-list(), parse-sequence())      else : List()``

Notice the use of `attempt` to first try parsing a symbol, and then if that fails to then try parsing a number, followed by trying to parse a list.

### Parsing Lists

The `parse-list` function eats and returns the next list from `chars`. A list is simply a sequence of s-expressions surrounded by `()` characters. If the next character is not an opening parenthesis then `parse-list` fails.

``defn parse-list () -> List :      if peek(chars) != '(' : fail()   next(chars)   val items = parse-sequence()   if empty?(chars) : fatal("Unclosed opening parenthesis.")   else if peek(chars) == ')' : (next(chars), items)   else : fatal("Expected closing parenthesis but got %~." % [next(chars)])``

### Driver

Finally, to start off the function, we attempt to read as many s-expressions as possible from `chars` using `parse-sequence`

``val items = parse-sequence()if empty?(chars) : itemselse : fatal("Unexpected character: %~." % [next(chars)])``

### Listing

Here is the complete definition of `parse-sexp`.

``defn parse-sexp (sexp:String) :   val chars = to-seq(sexp)   defn eat-while (pred?: Char -> True|False) -> String :      string-join(take-while(pred?, chars))   defn eat-whitespace () -> False :      eat-while({_ == ' '})      false      defn parse-symbol () -> Symbol :      if not letter?(peek(chars)) : fail()      to-symbol(eat-while(letter?))            defn parse-number () -> Int :      if not digit?(peek(chars)) : fail()      val x = to-int(eat-while(digit?))      if x is-not Int : fail()      x as Int   defn parse-sequence () -> List :      eat-whitespace()      if empty?(chars) :         List()      else :         attempt : cons(parse-symbol(), parse-sequence())         else attempt : cons(parse-number(), parse-sequence())         else attempt : cons(parse-list(), parse-sequence())         else : List()         defn parse-list () -> List :         if peek(chars) != '(' : fail()      next(chars)      val items = parse-sequence()      if empty?(chars) : fatal("Unclosed opening parenthesis.")      else if peek(chars) == ')' : (next(chars), items)      else : fatal("Expected closing parenthesis but got %~." % [next(chars)])   val items = parse-sequence()   if empty?(chars) : items   else : fatal("Unexpected character: %~." % [next(chars)])``

### Trying it Out

Let's try it out on the following string.

``do(println, parse-sexp("This (is) (commonly (called an (S) (Expression)))"))``

When compiled and ran it prints out

``This(is)(commonly (called an (S) (Expression)))``

### Unveiling The Internals

The `attempt` construct is just syntactic sugar for a function call.

``attempt : conseqelse : alt``

is equivalent to

``with-attempt(   fn () : conseq   fn () : alt)``

As an exercise, try and implement your own `with-attempt` function by using the `label` construct.

## Exception Handling

Our s-expression parser from the previous example fails when called with invalid input (though with very nice error messages). Here is what happens if we forget a closing parenthesis at the end.

``do(println, parse-sexp("This (is) (commonly (called an (S) (Expression))"))``

Compiling and running the above prints out

``FATAL ERROR: Unclosed opening parenthesis.   at test.stanza:39.25   at test.stanza:32.29   at core/core.stanza:3725.13   at core/core.stanza:847.16   at core/core.stanza:3724.14   ...``

But what if we cannot guarantee that the input is correct? Suppose we want users to type an arbitrary string into the terminal and print the parsed s-expression if it's well formed, or else ask them to try again if it's not.

A potential solution would be to write another function called `sexp?` that returns `true` or `false` depending on whether its argument is a well formed string. But checking whether an s-expression is well formed is almost as much work as parsing it, so that's an inefficient solution.

Stanza provides us a mechanism for handling this called exceptions.

### Exception Objects

The first step is to declare our own `Exception` types, one for each type of error the parser can encounter.

``defstruct UnclosedParenthesis <: Exceptiondefmethod print (o:OutputStream, e:UnclosedParenthesis) :   print(o, "Unclosed opening parenthesis.")   defstruct UnmatchedParenthesis <: Exception : (char:Char)defmethod print (o:OutputStream, e:UnmatchedParenthesis) :   print(o, "Expected closing parenthesis but got %~." % [char(e)])   defstruct UnexpectedCharacter <: Exception : (char:Char)defmethod print (o:OutputStream, e:UnexpectedCharacter) :   print(o, "Unexpected character: %~." % [char(e)])``

There are three different errors that are detected by our parser.

1. The string is missing a closing parenthesis at the end.
2. We are currently reading a list and encountered a strange character.
3. We've read as many s-expressions as possible and there is a strange character left over.

### Throwing Exceptions

The next step is to change the calls to `fatal` to calls to `throw` with our newly defined `Exception` objects.

``defn parse-sexp (sexp:String) :   ...         defn parse-list () -> List :         ...      if empty?(chars) : throw(UnclosedParenthesis())      else if peek(chars) == ')' : (next(chars), items)      else : throw(UnmatchedParenthesis(next(chars)))   val items = parse-sequence()   if empty?(chars) : items   else : throw(UnexpectedCharacter(next(chars)))``

### Catching Exceptions

The final step is to catch the thrown exceptions. We can decide which types of exceptions to catch, and which not to. In this example, we'll assume that the string doesn't contain any strange characters and catch only the unclosed parenthesis error.

``try :   do(println, parse-sexp("This (is) (commonly (called an (S) (Expression))"))catch (e:UnclosedParenthesis) :   println("You forgot to close an opening parenthesis. Please try again.")``

Compiling and running the program now prints out

``You forgot to close an opening parenthesis. Please try again.``

Here is the general form of the `try` construct.

``try :   bodycatch (e:ExceptionA) :   a-handlercatch (e:ExceptionB) :   b-handler...   ``

The `try` construct evaluates the given `body` after installing the given exception handlers. If `body` is evaluated without ever calling `throw` then its result is returned by `try`. If `body` calls `throw` with some `Exception` object, then `try` immediately searches for the first exception handler that can accept the `Exception` object and returns the result of evaluating that handler.

## Generators

The control flow constructs you've been introduced to so far, labeled scopes, attempts and failures, and exceptions, have all served the purpose of leaving a block of code. Generators are the first control flow construct you will learn capable of resuming a block of code.

Here is a generator that yields the first three positive integers.

``val xs:Seq<Int> = generate<Int> :   println("Yielding One")   yield(1)   println("Yielding Two")   yield(2)   println("Yielding Three")   yield(3)``

Notice that the `generate` construct returns a `Seq`. Let's try printing out the items in the sequence.

``println("The first item in xs is")println(next(xs))println("The second item in xs is")println(next(xs))println("The third item in xs is")println(next(xs))``

Compiling and running the above prints out

``The first item in xs isYielding One1The second item in xs isYielding Two2The third item in xs isYielding Three3``

### The Ability to Resume

It's worth paying attention to the order in which the messages are printed out. The snippet

``println("The first item in xs is")println(next(xs))``

by itself, prints out

``The first item in xs isYielding One1``

Thus the call to `next(xs)` causes control to enter the block of code in the `generate` construct. The message `"Yielding One"` is printed out, and then the call to `yield(1)` leaves the `generate` construct and `1` is the return value of `next(xs)`.

The next snippet

``println("The second item in xs is")println(next(xs))``

prints out

``The second item in xs isYielding Two2``

Thus the call to `next(xs)` causes control to re-enter the block `generate` construct, resuming from just after the first call to `yield`. The message `"Yielding Two"` is printed out, and then the call to `yield(2)` leaves the `generate` construct once again and `2` is the return value of the second call to `next(xs)`.

The last snippet

``println("The third item in xs is")println(next(xs))``

prints out

``The third item in xs isYielding Three3``

Similarly, the call to `next(xs)` resumes the block in the `generate` construct from just after the second call to `yield`. The message `"Yielding Three"` is printed out, and then the call to `yield(3)` leaves the `generate` construct once again and `3` is the return value of the third call to `next(xs)`.

Thus the `generate` construct provides a very convenient way of creating a lazily constructed sequence.

### General Form

Here is the general form of the `generate` construct.

``generate<T> :   body``

`generate` returns a `Seq<T>` by lazily executing the given `body` in a scope containing the generation functions, `yield` and `break`

`yield` is of type `T -> False` and its argument becomes an element in the generated `Seq`. Execution of the generate block pauses at `yield`, and is resumed on the next call to `next` on the sequence.

`break` is both of type `() -> Void` and `T -> Void`. If no argument is given to `break`, then execution of the generate block ends here and marks the end of the generated sequence. If an argument is given to `break`, then that element is first yielded before the generate block is ended.

If the generated type, `T`, is not explicitly provided, then it is assumed to be `?` by default.

### Example: Flattening a Tuple

In this example, we'll determine whether two tuples contain the same elements as each other if we lay out their elements in depth-first order. For example, the tuple

``[[1] [2 [3]] [[4 5] 6]]``

contains the elements `1``2``3``4``5``6` once laid out in depth-first order.

Here's the most straightforward way of doing this. We'll write a function called `flatten` that returns a `Vector` containing a tuple's elements in depth-first order.

``defn flatten (x:Tuple) -> Vector :   val v = Vector<?>()   defn loop (x) :      match(x) :         (x:Tuple) : do(loop, x)         (x) : add(v, x)   loop(x)            v      ``

Let's try it out.

``println(flatten([[1] [2 [3]] [[4 5] 6]]))``

Compiling and running the above prints out

``[1 2 3 4 5 6]``

To check whether two tuples contain the same elements, we can just flatten each of them and then compare the elements.

``defn same-elements? (a:Tuple, b:Tuple) :   if all?(equal?, flatten(a), flatten(b)) :      println("%_ and %_ have the same elements." % [a, b])   else :      println("%_ and %_ have different elements." % [a, b])``

Let's test it out on the following tuples.

``same-elements?(   [[1] [2 [3]] [[4 5] 6]]   [1 [[2 3 4] [5]] [6]])same-elements?(   [[1] [2 [3]] [[4 5] 6]]   [[[0] 2] [3 [4 5]] 6])``

Compiling and running the above prints out

``[[1] [2 [3]] [[4 5] 6]] and [1 [[2 3 4] [5]] [6]] have the same elements.[[1] [2 [3]] [[4 5] 6]] and [[[0] 2] [3 [4 5]] 6] have different elements.``

Notice though, that in both cases, we computed a full flattening of both tuples before checking to see whether they are equal. This is obviously inefficient in the second case since we can tell they are clearly different just by examining their first element. How do we avoid computing the full flattening?

The solution is to lazily compute the flattening. Let's change `flatten` to use the `generate` construct to lazily compute the flattened tuples. To track how much of the tuples are being flattened let's also add a print statement.

``defn flatten (x:Tuple) -> Seq :   val index = to-seq(0 to false)   generate :      defn loop (x) :         match(x) :            (x:Tuple) :               do(loop, x)            (x) :               println("Yielding Item %_" % [next(index)])               yield(x)      loop(x)         ``

Compiling and running the program again prints out

``Yielding Item 0Yielding Item 0Yielding Item 1Yielding Item 1Yielding Item 2Yielding Item 2Yielding Item 3Yielding Item 3Yielding Item 4Yielding Item 4Yielding Item 5Yielding Item 5[[1] [2 [3]] [[4 5] 6]] and [1 [[2 3 4] [5]] [6]] have the same elements.Yielding Item 0Yielding Item 0[[1] [2 [3]] [[4 5] 6]] and [[[0] 2] [3 [4 5]] 6] have different elements.``

Thus the results are the same as before, and you can see that, for the second comparison, both generators (one for each tuple) are only computing up to the first element.

## Coroutines

The `label``attempt``try`, and `generate` constructs are all specific usage patterns of Stanza's targetable coroutine system. Here we'll show you how to use the coroutine system in its full generality. It is rare in daily programming to encounter a problem that requires a use of coroutines that isn't already handled by one of the special case constructs. But for implementing libraries and frameworks that make heavy use of concurrency and non-standard control flow, coroutines may be indispensable.

### Sending Things Out

Here is the function that will represent our coroutine body.

``defn my-process (co:Coroutine<Int,String>, a:Int) -> String :   println("Passing out Timon")   suspend(co, "Timon")   println("Passing out and")   suspend(co, "and")   println("Passing out Pumbaa")   suspend(co, "Pumbaa")   println("Coroutine is done")   "Done"``

The type `Coroutine<Int,String>` represents a coroutine for which integers are sent into the coroutine, and for which strings are sent back from the coroutine. The function for sending values out of the coroutine is `suspend`

Let's now create our coroutine object and resume it a few times.

``println("Create coroutine")val co = Coroutine<Int,String>(my-process)println("\nResume with 42")val x = resume(co, 42)println("Got back x = %_" % [x])println("\nResume with 43")val y = resume(co, 43)println("Got back y = %_" % [y])println("\nResume with 44")val z = resume(co, 44)println("Got back z = %_" % [z])println("\nResume with 45")val w = resume(co, 45)println("Got back w = %_" % [w])``

Notice that `resume` is called with integers. When the above is compiled and ran it prints out

``Create coroutineResume with 42Passing out TimonGot back x = TimonResume with 43Passing out andGot back y = andResume with 44Passing out PumbaaGot back z = PumbaaResume with 45Coroutine is doneGot back w = Done``

Thus `suspend` acts much like `yield` did for the `generate` construct, and `resume` acts much like `next` did. This is no accident of course. The `generate` construct is implemented in terms of `suspend` and `resume` underneath.

### Breaking Things Off

In addition to `suspend`, a function called `break` can also be used to send values out of a coroutine. The difference is that a call to `break` cannot later be resumed.

Let's change our `my-process` function to send out `"Pumbaa"` with `break` instead of `suspend`.

``defn my-process (co:Coroutine<Int,String>, a:Int) -> String :   println("Passing out Timon")   suspend(co, "Timon")   println("Passing out and")   suspend(co, "and")   println("Passing out Pumbaa")   break(co, "Pumbaa")   println("Coroutine is done")   "Done"``

Compiling and running the program again prints out

``Create coroutineResume with 42Passing out TimonGot back x = TimonResume with 43Passing out andGot back y = andResume with 44Passing out PumbaaGot back z = PumbaaResume with 45FATAL ERROR: Cannot resume coroutine. Coroutine is already closed.   at core/core.stanza:984.13   at core/core.stanza:862.16   at core/core.stanza:897.40   at core/core.stanza:862.16   at test.stanza:31.8``

The coroutine is closed after the call to `break`, and thus our call to `resume` fails.

### Sending Things In

The obvious unanswered question now is: what is happening with the `42``43``44`, and `45` values that `resume` is being called with? To answer that, let's update our `my-process` function to print out the return values of `suspend` (and change the call to `break` back into `suspend`).

``defn my-process (co:Coroutine<Int,String>, a:Int) -> String :   println("Came in a = %_" % [a])   println("Passing out Timon")   val b = suspend(co, "Timon")   println("Came in b = %_" % [b])   println("Passing out and")   val c = suspend(co, "and")   println("Came in c = %_" % [c])   println("Passing out Pumbaa")   val d = suspend(co, "Pumbaa")   println("Came in d = %_" % [d])   println("Coroutine is done")   "Done"println("Create coroutine")val co = Coroutine<Int,String>(my-process)println("\nResume with 42")val x = resume(co, 42)println("Got back x = %_" % [x])println("\nResume with 43")val y = resume(co, 43)println("Got back y = %_" % [y])println("\nResume with 44")val z = resume(co, 44)println("Got back z = %_" % [z])println("\nResume with 45")val w = resume(co, 45)println("Got back w = %_" % [w])``

Compiling and running the program again prints out

``Create coroutineResume with 42Came in a = 42Passing out TimonGot back x = TimonResume with 43Came in b = 43Passing out andGot back y = andResume with 44Came in c = 44Passing out PumbaaGot back z = PumbaaResume with 45Came in d = 45Coroutine is doneGot back w = Done``

Thus, `suspend` sends its argument out from the coroutine, and returns the value sent into the coroutine. `resume` sends its argument into the coroutine, and returns the value sent out from the coroutine.

### Closing Things Off

From outside the coroutine body, we may also choose to close a coroutine when we're finished with it. Let's try closing our coroutine after getting back `"Pumbaa"`.

``println("Create coroutine")val co = Coroutine<Int,String>(my-process)println("\nResume with 42")val x = resume(co, 42)println("Got back x = %_" % [x])println("\nResume with 43")val y = resume(co, 43)println("Got back y = %_" % [y])println("\nResume with 44")val z = resume(co, 44)println("Got back z = %_" % [z])close(co)println("\nResume with 45")val w = resume(co, 45)println("Got back w = %_" % [w])``

Compiling and running the above prints out

``Create coroutineResume with 42Came in a = 42Passing out TimonGot back x = TimonResume with 43Came in b = 43Passing out andGot back y = andResume with 44Came in c = 44Passing out PumbaaGot back z = PumbaaResume with 45FATAL ERROR: Cannot resume coroutine. Coroutine is already closed.   at core/core.stanza:984.13   at core/core.stanza:862.16   at core/core.stanza:897.40   at core/core.stanza:862.16   at test.stanza:40.8``

### Checking a Coroutine's Status

There are two functions for checking on the status of a coroutine, `active?` and `open?`

Calling `active?` on a coroutine will return `true` if the coroutine's body is currently running, and `false` otherwise. Only active coroutines can be suspended or broken from.

Calling `open?` on a coroutine will return `true` if the coroutine's body is not currently running and open to be resumed. Only open coroutines can be resumed.

### Nested Coroutines

A coroutine may also launch more coroutines. Notice that unlike `yield`, the calls to `suspend``break`, and `resume` explicitly requires, as its first argument, the target coroutine. Being able to explicitly designate the target of the `suspend``break`, and `resume` operations are key to allowing nested coroutines to work properly.

Consider the following code, where the coroutine, `co1`, launches a second coroutine, `co2`, within its body. Then within `co2`'s body, there are `suspend` and `break` calls on both `co1` and `co2`. Pay attention to how this interacts.

``val co1 = Coroutine<False,Int> \$ fn (co1, x0) :   val co2 = Coroutine<False,False> \$ fn (co2, y0) :      for i in 0 to false do :         suspend(co1, i)         if i == 5 :            println("Breaking from coroutine 2!")            break(co2, false)   resume(co2, false)   -1while open?(co1) :   println(resume(co1, false))``

Compiling and running the above prints out

``012345Breaking from coroutine 2!-1``

The two nested coroutines are quite confusing. To get a better sense of what's happening, let's rewrite the second coroutine using the special case `label` construct.

``val co1 = Coroutine<False,Int> \$ fn (co1, x0) :   label<False> break :      for i in 0 to false do :         suspend(co1, i)         if i == 5 :            println("Breaking from coroutine 2!")            break(false)   -1while open?(co1) :   println(resume(co1, false))``

Compiling and running the above prints out the same message as before.

It is highly unlikely that you will feel the desire to directly launch new coroutines from within other coroutines, as we did here. But this example shows that they nest appropriately and generally do the right thing. Thus, for whatever abstractions you build on top of Stanza's targetable coroutine system, you can rest assured that they will recurse and compose correctly.

## Example: Key Listener

The following example demonstrates using coroutines to easily implement a key listener that translates individual key presses into events on strings.

Let us define a `KeyListener` type, and its fundamental operation.

``deftype KeyListenerdefmulti key-pressed (c:Char) -> False``

`KeyListener` object listens to individual key presses from a keyboard and translates them into higher level events. Here is the definition of the constructor function for a `KeyListener`.

``defn KeyListener (entered: String -> False) -> KeyListener``

`KeyListener` takes a callback function called `entered` that accepts `String` objects. Our `KeyListener` translates key presses into calls to `entered` on space-separated words. It also supports deleting characters with the backspace key, entering of double-quoted strings, and escaped double-quotes within a double-quoted string. Here is specifically what it has to do.

1. A `KeyListener` has an internal buffer for storing characters. When keys corresponding to letters are pressed, they are stored into the internal buffer.
2. When the backspace key is pressed, the last character is deleted from the internal buffer.
3. Once a full word is completed (indicated by the spacebar being pressed), the `entered` function should be called with the contents of the internal buffer.
4. If the double quote key is pressed, then this indicates that a string is being started, and all subsequent characters until the next double quote should be stored in the internal buffer. Upon completion of the string, the `entered` function should be called with the entire contents of the internal buffer.
5. During entering of a string, if a backslash character followed by a double quote character is entered, then the double quote character is stored in the internal buffer, and entering of the string continues. If the backslash character is not followed by a double quote then both characters are ignored.

### Coroutine Framework

Here is the basic framework that we will use to ease programming the `KeyListener`.

``defn KeyListener (entered: String -> False) -> KeyListener :   val co = Coroutine<Char,False> \$ fn (co, c0) :      ;Retrieve the next character      defn next-char () :         suspend(co, false)      ...   new KeyListener :      defmethod key-pressed (this, c:Char) :         resume(co, c)``

We immediately create a coroutine that accepts characters and sends back dummy values of type `False`. Within the coroutine body, the helper function `next-char` requests the next character by suspending the coroutine and returning the next character sent back into the coroutine. A new `KeyListener` object is returned that calls `resume` on the coroutine whenever a key is pressed.

### Buffer Managing Routines

The following definitions within the coroutine body help us manage the `KeyListener`'s internal buffer.

``;Buffer commandsval buffer = Vector<Char>()defn pop-char () :   if not empty?(buffer) :      pop(buffer)defn add-char (c:Char) :   add(buffer, c)defn empty-buffer () :   entered(string-join(buffer))   clear(buffer)``

The buffer is represented as a vector of characters. `pop-char` removes the last character in the buffer if possible. `add-char` adds the given character to the end of the buffer. `empty-buffer` calls the `entered` callback with the contents of the buffer, and then clears the buffer.

### Dispatch Mode

The key press parser operates in a number of different modes. The default mode is the dispatch mode, which determines which mode to next enter based on the previously pressed key.

``;Dispatch modedefn* parse (c:Char) :   if letter?(c) :      parse-word(c)   else if c == '\"' :      parse-string(next-char())   else :      parse(next-char())``

If a letter key was pressed, then we start parsing a word event. If the double-quote key is pressed, then we start parsing a string event. Otherwise, the key press is ignored.

### Word Mode

The word parsing mode accepts key presses until one word is completed.

``;Word parsing modedefn* parse-word (c:Char) :   if letter?(c) :      add-char(c)      parse-word(next-char())   else if c == '\b' :      pop-char()      parse-word(next-char())   else if (c == ' ') or (c == '\"') :      empty-buffer()      parse(c)   else :      parse-word(next-char())``

If the last key pressed was a letter, then that letter is added to the buffer. If the last key was a backspace, then we delete a character from the buffer. If the last key was the spacebar or the double-quote key, then the word is completed. We empty the buffer and then go back to the dispatch mode. All other keys are ignored.

### String Mode

The string parsing mode accepts key presses until another (un-escaped) double-quote key finishes the string.

``;String parsing modedefn* parse-string (c:Char) :   if c == '\"' :      empty-buffer()      parse(next-char())   else if c == '\b' :      pop-char()      parse-string(next-char())   else if c == '\\' :      if next-char() == '\"' : add-char('\"')      parse-string(next-char())   else :      add-char(c)      parse-string(next-char())``

If the last key pressed was the double-quote key then the string is completed. We empty the buffer and then go back to the dispatch mode. If the last key was a backspace, then we delete a character from the buffer. If the last key was the backslash key, then we add a double-quote to the buffer if the following key is a double-quote. Otherwise both keys are ignored. Finally, all other characters are added to the buffer.

### Testing the KeyListener

Here is the entire `KeyListener` constructor function.

``defn KeyListener (entered: String -> False) -> KeyListener :   val co = Coroutine<Char,False> \$ fn (co, c0) :      ;Retrieve the next character      defn next-char () :         suspend(co, false)               ;Buffer commands      val buffer = Vector<Char>()      defn pop-char () :         if not empty?(buffer) :            pop(buffer)      defn add-char (c:Char) :         add(buffer, c)      defn empty-buffer () :         entered(string-join(buffer))         clear(buffer)      ;Dispatch mode      defn* parse (c:Char) :         if letter?(c) :            parse-word(c)         else if c == '\"' :            parse-string(next-char())         else :            parse(next-char())      ;Word parsing mode      defn* parse-word (c:Char) :         if letter?(c) :            add-char(c)            parse-word(next-char())         else if c == '\b' :            pop-char()            parse-word(next-char())         else if (c == ' ') or (c == '\"') :            empty-buffer()            parse(c)         else :            parse-word(next-char())      ;String parsing mode      defn* parse-string (c:Char) :         if c == '\"' :            empty-buffer()            parse(next-char())         else if c == '\b' :            pop-char()            parse-string(next-char())         else if c == '\\' :            if next-char() == '\"' : add-char('\"')            parse-string(next-char())         else :            add-char(c)            parse-string(next-char())                  ;Launch!      parse(c0)   new KeyListener :      defmethod key-pressed (this, c:Char) :         resume(co, c)``

Let's try it out on some simulated key presses.

``defn keys-pressed (kl:KeyListener, cs:Seqable<Char>) :   do(key-pressed{kl, _}, cs)defn main () :   val kl = KeyListener \$ fn (s) :      println("String entered: %_" % [s])         ;Test backspace      keys-pressed(kl, "Timom\bn ")      ;Test simple word   keys-pressed(kl, "and ")   ;Test backspace against empty buffer   keys-pressed(kl, "P\b\b\b\bPumbaa")      ;Test unrecognized characters   keys-pressed(kl, " a#\$!re")      ;Test strings with escaped quotes   keys-pressed(kl, \<S>"\"good\" friends!!"<S>)main()``

Note that

``\<S>literal !@#\$%\|" characters<S>``

is Stanza's syntax for a literal un-escaped string. All characters between the starting `<S>` tag and the ending `<S>` tag are part of the string. Any tag may be used in place of `S`.

Compiling and running the above prints out

``String entered: TimonString entered: andString entered: PumbaaString entered: areString entered: "good" friends!!``

Our `KeyListener` calls the callback function at the correct times and with the correct input!

The coroutine mechanism allowed us to keep the code fairly straightforward and modular, even though the logic behind the `KeyListener` itself is actually quite sophisticated. As an exercise, you may try to implement an equivalent `KeyListener` function without using the coroutine mechanism to fully appreciate how tedious and error-prone it is.