# Loop subsystem

Dusk's "main" execution loop is to repeatedly fetch word from its input source
and execute it. If the input source is interactive, it means that it spends the
vast majority of its time waiting for this source.

If you install the loop subsystem, you can use this time to do other tasks one
after the other. That system, living in sys/loop, is the heart of Dusk's
cooperative multi-tasking. It's a linked list of routines that are called one
after the other whenever "idle" is called.

You could, for example, want to maintain some debug information at specific
coordinates of your Grid subsystem. Or, if you have a mouse subsystem, you'll
want to regularly update its coordinates. You would do that through the loop.

## Implementation

Dusk's core has a "idle" alias that simply points to "noop". When you load
sys/loop, it makes "idle" point to its implementation. Because sys/kbd calls
"idle" in its "key" implementation, this means that as soon as you load
sys/loop, that loop is going to be called repeatedly.

Initially, it's empty. You can add words with "loopadd" ( w -- ). "w" is a
pointer to a word that must have a signature ( -- ).

The loop is a list of routines in which we keep track of the next routine to
call. Calling "idle" simply calls that routine select the next one in the list
for the next "idle" call. In other words, "idle" calls *one* item in the loop.

"idle" doesn't have to be called only by "key". In can also be called by a word
that is doing a time-intensive task. That those tasks call "idle" is what
enables multi-tasking.

There's an important caveat with idle: if you call it often enough, you are
likely to call the exact same word that is at the origin of your time-consuming
loop. It is therefore important to organize the code in ways that don't result
in infinite recursion.

For example, if one of your loop task is to check for incoming data in a serial
port, then checking this is quick and usually returns quickly. If the serial
port indicates that a chunk of data needs to be processed and that you will at
some point be waiting for the hardware to respond, then the right thing to do is
to call for "idle" while you wait. However, before you do, it's impotant to set
a flag somewhere that will prevent your main routine from entering the "waiting
for incoming data" code path or else you'll blow your stack in infinite
recursion.

## API

idle ( -- )
  Call the next word of the loop.

loopadd ( w -- )
  Add word "w" to the loop.

.theloop ( -- )
  Prints the list of words in the loop and initialization sequence.
